home *** CD-ROM | disk | FTP | other *** search
Wrap
Text File | 2002-12-11 | 1.0 MB | 32,710 lines
Text Truncated. Only the first 1MB is shown below. Download the file for the complete contents.
/* ** replsys.sql 1997/02/12 22:03 ** ** ** Copyright Microsoft, Inc. 1998-2000 ** All Rights Reserved. */ dump tran master with no_log go exec dbo.sp_configure 'update',1 go reconfigure with override go set ANSI_NULLS off go use master go exec dbo.sp_MS_upd_sysobj_category 1 --Capture time for use at the end go if exists( select * from sysobjects where type = 'P ' and name = N'sp_getarticlepkcolbitmap') begin drop procedure sp_getarticlepkcolbitmap end go if exists( select * from sysobjects where type = 'P ' and name = N'sp_isarticlecolbitset' ) begin drop procedure sp_isarticlecolbitset end go if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSsubst_filter_name') drop procedure sp_MSsubst_filter_name go if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSretrieve_publication_attributes') drop procedure sp_MSretrieve_publication_attributes go if exists (select * from sysobjects where type = 'P ' and name = 'sp_MScleanup_publication_ADinfo') drop procedure sp_MScleanup_publication_ADinfo go if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSCleanupForPullReinit') drop procedure sp_MSCleanupForPullReinit if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSsubst_filter_names') drop procedure sp_MSsubst_filter_names go if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSreplcheck_name') drop procedure sp_MSreplcheck_name go if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSreplcheck_publish') drop procedure sp_MSreplcheck_publish go if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSsetaccesslist') drop procedure sp_MSsetaccesslist go if exists (select * from sysobjects where type = 'P ' and name = 'sp_MScheck_subscription') drop procedure sp_MScheck_subscription go if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSenumcolumns') drop procedure sp_MSenumcolumns go if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSlocktable') drop procedure sp_MSlocktable go if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSreplcheck_connection') drop procedure sp_MSreplcheck_connection go if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSrepl_PAL_rolecheck') drop procedure sp_MSrepl_PAL_rolecheck go if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSreplcheck_pull') drop procedure sp_MSreplcheck_pull go if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSchange_retention') drop procedure sp_MSchange_retention if exists (select * from sysobjects where type = 'P ' and name = 'sp_MShelp_identity_property') drop procedure sp_MShelp_identity_property go if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSreplcheck_qv') drop procedure sp_MSreplcheck_qv go if exists (select * from sysobjects where type = 'P' and name = 'sp_MSreleaseSlotLock') drop procedure sp_MSreleaseSlotLock if exists (select * from sysobjects where type = 'P' and name = 'sp_MSacquireSlotLock') drop procedure sp_MSacquireSlotLock go if exists (select * from sysobjects where type = 'P' and name = 'sp_MSacquireHeadofQueueLock') drop procedure sp_MSacquireHeadofQueueLock go if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSpublicationcleanup') drop procedure sp_MSpublicationcleanup if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSUpgradeConflictTable') drop procedure sp_MSUpgradeConflictTable if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSaddanonymousreplica') drop procedure sp_MSaddanonymousreplica if exists (select * from sysobjects where type = 'P' and name = 'sp_reinitmergepullsubscription') drop procedure sp_reinitmergepullsubscription if exists (select * from sysobjects where type = 'P ' and name = 'sp_expired_subscription_cleanup') drop procedure sp_expired_subscription_cleanup if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSarticlecleanup') drop procedure sp_MSarticlecleanup if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSdroparticleprocs') drop procedure sp_MSdroparticleprocs if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSdroparticletriggers') drop procedure sp_MSdroparticletriggers if exists (select * from sysobjects where type = 'P ' and name = 'sp_MScheckvalidsystables') drop procedure sp_MScheckvalidsystables if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSreplcheck_subscribe') drop procedure sp_MSreplcheck_subscribe go if exists (select * from sysobjects where type = 'P ' and name = 'sp_replicationoption') drop procedure sp_replicationoption go if exists (select * from sysobjects where type = 'P ' and name = 'sp_helpreplicationoption') drop procedure sp_helpreplicationoption go if exists (select * from sysobjects where type in ('P ') and name = 'sp_MSmergesubscribedb') drop procedure sp_MSmergesubscribedb if exists (select * from sysobjects where type in ('P ') and name = 'sp_MSremovedbreplication') drop procedure sp_MSremovedbreplication if exists (select * from sysobjects where type = 'P ' and name = 'sp_addpullsubscription') drop procedure sp_addpullsubscription if exists (select * from sysobjects where type = 'P ' and name = 'sp_reinitpullsubscription') drop procedure sp_reinitpullsubscription if exists (select * from sysobjects where type = 'P ' and name = 'sp_addmergepullsubscription') drop procedure sp_addmergepullsubscription if exists (select * from sysobjects where type = 'P ' and name = 'sp_dropmergepullsubscription') drop procedure sp_dropmergepullsubscription if exists (select * from sysobjects where type = 'P ' and name = 'sp_adjustpublisheridentityrange') drop procedure sp_adjustpublisheridentityrange if exists (select * from sysobjects where type = 'P ' and name = 'sp_changemergepullsubscription') drop procedure sp_changemergepullsubscription if exists (select * from sysobjects where type = 'P ' and name = 'sp_helpmergepullsubscription') drop procedure sp_helpmergepullsubscription if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSchange_priority') drop procedure sp_MSchange_priority if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSdrop_mergesystables') drop procedure sp_MSdrop_mergesystables if exists (select * from sysobjects where type = 'P ' and name = 'sp_MScreate_mergesystables') drop procedure sp_MScreate_mergesystables go if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSupdatesharedagentproperties') drop procedure sp_MSupdatesharedagentproperties if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSfixupsharedagentproperties') drop procedure sp_MSfixupsharedagentproperties if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSfixupdistributorinfo') drop procedure sp_MSfixupdistributorinfo if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSfixupdistributorsecurity') drop procedure sp_MSfixupdistributorsecurity if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSfixupftpinfo') drop procedure sp_MSfixupftpinfo if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSfixupaltsnapshotfolder') drop procedure sp_MSfixupaltsnapshotfolder if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSfixupworkingdirectory') drop procedure sp_MSfixupworkingdirectory if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSfixupuseftp') drop procedure sp_MSfixupuseftp if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSfixupagentoffloadinfo') drop procedure sp_MSfixupagentoffloadinfo go if exists (select * from sysobjects where type = 'P ' and name = 'sp_addpullsubscription_agent') drop procedure sp_addpullsubscription_agent if exists (select * from sysobjects where type = 'P ' and name = 'sp_helpsubscription_properties') drop procedure sp_helpsubscription_properties if exists (select * from sysobjects where type = 'P ' and name = 'sp_change_subscription_properties') drop procedure sp_change_subscription_properties if exists (select * from sysobjects where type = 'P' and name = 'sp_MSget_pullsubsagent_owner') drop procedure sp_MSget_pullsubsagent_owner if exists (select * from sysobjects where type = 'P' and name = 'sp_MSget_mergepullsubsagent_owner') drop procedure sp_MSget_mergepullsubsagent_owner if exists (select * from sysobjects where type = 'P ' and name = 'sp_addmergepullsubscription_agent') drop procedure sp_addmergepullsubscription_agent if exists (select * from sysobjects where type = 'P ' and name = 'sp_droppullsubscription') drop procedure sp_droppullsubscription if exists (select * from sysobjects where type = 'P ' and name = 'sp_vupgrade_publisherdb') drop procedure sp_vupgrade_publisherdb if exists (select * from sysobjects where type = 'P ' and name = 'sp_vupgrade_publisher') drop procedure sp_vupgrade_publisher if exists (select * from sysobjects where type = 'P ' and name = 'sp_MScopyregvalue') drop procedure sp_MScopyregvalue if exists (select * from sysobjects where type = 'P ' and name = 'sp_vupgrade_registry') drop procedure sp_vupgrade_registry -- this proc renamed if exists (select * from sysobjects where type = 'P ' and name = 'sp_vupdate_syscol_status') drop procedure sp_vupdate_syscol_status if exists (select * from sysobjects where type = 'P ' and name = 'sp_vupgrade_syscol_status') drop procedure sp_vupgrade_syscol_status if exists (select * from sysobjects where type = 'P ' and name = 'sp_helppullsubscription') drop procedure sp_helppullsubscription if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSunmarkreplinfo') drop procedure sp_MSunmarkreplinfo if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSmarkreplinfo') drop procedure sp_MSmarkreplinfo if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSunmarkschemaobject') drop procedure sp_MSunmarkschemaobject if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSmarkschemaobject') drop procedure sp_MSmarkschemaobject if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSunmarkifneeded') drop procedure sp_MSunmarkifneeded if exists (select * from sysobjects where type = 'P ' and name = 'sp_MStable_has_unique_index') drop procedure sp_MStable_has_unique_index if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSreplraiserror') drop procedure sp_MSreplraiserror if exists (select * from sysobjects where type = 'P ' and name = 'sp_check_sync_trigger') drop procedure sp_check_sync_trigger if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSreplicationcompatlevel') drop proc sp_MSreplicationcompatlevel if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSgenreplnickname') drop proc sp_MSgenreplnickname if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSenumallpublications') drop proc sp_MSenumallpublications if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSenumallsubscriptions') drop proc sp_MSenumallsubscriptions if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSenumsubscriptions') drop proc sp_MSenumsubscriptions if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSenumtranpublications') drop proc sp_MSenumtranpublications if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSenummergepublications') drop proc sp_MSenummergepublications if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSenum3rdpartypublications') drop proc sp_MSenum3rdpartypublications if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSenumthirdpartypublicationvendornames') drop proc sp_MSenumthirdpartypublicationvendornames if exists (select * from sysobjects where type = 'P' and name = 'sp_MSgetreplicainfo') drop procedure sp_MSgetreplicainfo if exists (select * from sysobjects where type = 'P ' and name = 'sp_subscription_cleanup') drop procedure sp_subscription_cleanup if exists (select * from sysobjects where type = 'P ' and name = 'sp_mergesubscription_cleanup') drop procedure sp_mergesubscription_cleanup if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSpad_command') drop procedure sp_MSpad_command if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSflush_command') drop procedure sp_MSflush_command if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSget_colinfo') drop procedure sp_MSget_colinfo if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSget_type') drop procedure sp_MSget_type if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSget_col_position') drop procedure sp_MSget_col_position if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSget_map_position') drop procedure sp_MSget_map_position if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSscript_where_clause') drop procedure sp_MSscript_where_clause if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSscript_params') drop procedure sp_MSscript_params if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSscript_procbodystart') drop procedure sp_MSscript_procbodystart if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSscript_begintrig1') drop procedure sp_MSscript_begintrig1 if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSscript_begintrig2') drop procedure sp_MSscript_begintrig2 if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSscript_endtrig') drop procedure sp_MSscript_endtrig if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSscript_trigger_variables') drop procedure sp_MSscript_trigger_variables if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSscript_trigger_assignment') drop procedure sp_MSscript_trigger_assignment if exists (select * from sysobjects where type = 'P ' and name = 'sp_validatemergepullsubscription') drop procedure sp_validatemergepullsubscription if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSscript_trigger_fetch_statement') drop procedure sp_MSscript_trigger_fetch_statement if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSscript_trigger_exec_rpc') drop procedure sp_MSscript_trigger_exec_rpc if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSscript_trigger_update_checks') drop procedure sp_MSscript_trigger_update_checks if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSscript_trigger_updates') drop procedure sp_MSscript_trigger_updates if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSscript_singlerow_trigger') drop procedure sp_MSscript_singlerow_trigger if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSscript_multirow_trigger') drop procedure sp_MSscript_multirow_trigger if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSscript_sync_ins_trig') drop procedure sp_MSscript_sync_ins_trig if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSscript_sync_upd_trig') drop procedure sp_MSscript_sync_upd_trig if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSscript_sync_del_trig') drop procedure sp_MSscript_sync_del_trig if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSget_synctran_column') drop procedure sp_MSget_synctran_column if exists (select * from sysobjects where type = 'P ' and name = 'sp_check_for_sync_trigger') drop procedure sp_check_for_sync_trigger if exists (select * from sysobjects where type = 'P ' and name = 'sp_addqueued_artinfo') drop procedure sp_addqueued_artinfo if exists (select * from sysobjects where type = 'P ' and name = 'sp_addsynctriggers') drop procedure sp_addsynctriggers if exists (select * from sysobjects where type = 'P ' and name = 'sp_setreplfailovermode') drop procedure sp_setreplfailovermode if exists (select * from sysobjects where type = 'P ' and name = 'sp_helpreplfailovermode') drop procedure sp_helpreplfailovermode if exists (select * from sysobjects where type = 'P ' and name = 'sp_helpreplicationdboption') drop procedure sp_helpreplicationdboption if exists (select * from sysobjects where type = 'P' and name = 'sp_MSgetreplnick') drop procedure sp_MSgetreplnick if exists (select * from sysobjects where type = 'P' and name = 'sp_MStestbit') drop procedure sp_MStestbit if exists (select * from sysobjects where type = 'P' and name = 'sp_MSsetbit') drop procedure sp_MSsetbit if exists (select * from sysobjects where type = 'P' and name = 'sp_MSinsertcontents') drop procedure sp_MSinsertcontents if exists (select * from sysobjects where type = 'P' and name = 'sp_MSupdatecontents') drop procedure sp_MSupdatecontents if exists (select * from sysobjects where type = 'P' and name = 'sp_MSdeletecontents') drop procedure sp_MSdeletecontents if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSadd_repl_job') drop procedure sp_MSadd_repl_job IF EXISTS (select * from sysobjects where name = 'sp_MScheck_agent_instance' and type = 'P') DROP PROCEDURE sp_MScheck_agent_instance IF EXISTS (select * from sysobjects where name = 'sp_MSenum_replsqlqueues' and type = 'P') DROP PROCEDURE sp_MSenum_replsqlqueues IF EXISTS (select * from sysobjects where name = 'sp_MSenum_replqueues' and type = 'P') DROP PROCEDURE sp_MSenum_replqueues if exists (select * from sysobjects where name = 'xp_mergexpusage') execute dbo.sp_dropextendedproc 'xp_mergexpusage' if exists (select * from sysobjects where name = 'sp_get_distributor' and type = 'P') drop procedure sp_get_distributor if exists (select * from sysobjects where name = 'sp_MSrepl_addrolemember' and type = 'P') drop procedure sp_MSrepl_addrolemember if exists (select * from sysobjects where name = 'sp_MSrepl_droprolemember' and type = 'P') drop procedure sp_MSrepl_droprolemember if exists (select * from sysobjects where name = 'sp_table_validation' and type = 'P') drop procedure sp_table_validation if exists (select * from sysobjects where name = 'sp_MScreate_sub_tables' and type = 'P') drop procedure sp_MScreate_sub_tables go if exists (select * from sysobjects where name = 'sp_MSupdate_mqserver_subdb' and type = 'P') drop procedure sp_MSupdate_mqserver_subdb if exists (select * from sysobjects where name = 'sp_removedbreplication' and type = 'P') drop procedure sp_removedbreplication if exists (select * from sysobjects where name = 'sp_MSBumpupCompLevel' and type = 'P') drop procedure sp_MSBumpupCompLevel if exists (select * from sysobjects where name = 'sp_cleanupdbreplication' and type = 'P') drop procedure sp_cleanupdbreplication if exists (select * from sysobjects where name = 'sp_removesrvreplication' and type = 'P') drop procedure sp_removesrvreplication if exists (select * from sysobjects where name = 'sp_vupgrade_subscription_databases' and type = 'P') drop procedure sp_vupgrade_subscription_databases if exists (select * from sysobjects where name = 'sp_vupgrade_MSsubscription_properties' and type = 'P') drop procedure sp_vupgrade_MSsubscription_properties if exists (select * from sysobjects where name = 'sp_vupgrade_mergetables' and type = 'P') drop procedure sp_vupgrade_mergetables if exists (select * from sysobjects where name = 'sp_vupgrade_subpass' and type = 'P') drop procedure sp_vupgrade_subpass if exists (select * from sysobjects where name = 'sp_vupgrade_subscription_tables' and type = 'P') drop procedure sp_vupgrade_subscription_tables if exists (select * from sysobjects where name = 'sp_vupgrade_replication' and type = 'P') drop procedure sp_vupgrade_replication if exists (select * from sysobjects where name = 'sp_vupgrade_distdb' and type = 'P') drop procedure sp_vupgrade_distdb if exists (select * from sysobjects where name = 'sp_vupgrade_replmsdb' and type = 'P') drop procedure sp_vupgrade_replmsdb if exists (select * from sysobjects where name = 'sp_restoredbreplication' and type = 'P') drop procedure sp_restoredbreplication if exists (select * from sysobjects where name = 'sp_MSget_publisher_rpc' and type = 'P') drop procedure sp_MSget_publisher_rpc if exists (select * from sysobjects where name = 'sp_link_publication' and type = 'P') drop procedure sp_link_publication if exists (select * from sysobjects where name = 'sp_MS_replication_installed' and type = 'P') drop procedure sp_MS_replication_installed if exists (select * from sysobjects where name = 'sp_MSunc_to_drive' and type = 'P') drop procedure sp_MSunc_to_drive if exists (select * from sysobjects where name = 'sp_MSdrop_object' and type = 'P') drop procedure sp_MSdrop_object if exists (select * from sysobjects where name = 'sp_MSregistersubscription' and type = 'P') drop procedure sp_MSregistersubscription if exists (select * from sysobjects where name = 'sp_MSunregistersubscription' and type = 'P') drop procedure sp_MSunregistersubscription if exists (select * from sysobjects where name = 'sp_MSsubscription_enabled_for_syncmgr' and type = 'P') drop procedure sp_MSsubscription_enabled_for_syncmgr if exists (select * from sysobjects where name = 'sp_MSrepl_linkedservers_rowset' and type = 'P') drop procedure sp_MSrepl_linkedservers_rowset if exists (select * from sysobjects where name = 'sp_MSrepl_isdbowner' and type = 'P') drop procedure sp_MSrepl_isdbowner if exists (select * from sysobjects where name = 'sp_MSget_qualified_name' and type = 'P') drop procedure sp_MSget_qualified_name if exists (select * from sysobjects where name = 'sp_MSscript_pkvar_assignment' and type = 'P') drop procedure sp_MSscript_pkvar_assignment go if exists (select * from sysobjects where name = 'sp_MSget_jobstate' and type = 'P') drop procedure sp_MSget_jobstate go if exists (select * from sysobjects where name = 'sp_browsemergesnapshotfolder' and type = 'P') drop procedure sp_browsemergesnapshotfolder go if exists (select * from sysobjects where name = 'sp_browsesnapshotfolder' and type = 'P') drop procedure sp_browsesnapshotfolder go if exists (select * from sysobjects where name = 'sp_MScopysnapshot' and type = 'P') drop procedure sp_MScopysnapshot go if exists (select * from sysobjects where name = 'sp_copymergesnapshot' and type = 'P') drop procedure sp_copymergesnapshot go if exists (select * from sysobjects where name = 'sp_copysnapshot' and type = 'P') drop procedure sp_copysnapshot go if exists (select * from sysobjects where name = 'sp_getsubscriptiondtspackagename' and type = 'P') drop procedure sp_getsubscriptiondtspackagename go if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSget_publication_from_taskname') drop procedure sp_MSget_publication_from_taskname go if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSrepl_check_server') drop procedure sp_MSrepl_check_server go if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSreset_synctran_bit') drop procedure sp_MSreset_synctran_bit go if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSreset_queue') drop procedure sp_MSreset_queue go if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSreset_queued_reinit') drop procedure sp_MSreset_queued_reinit go if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSinit_subscription_agent') drop procedure sp_MSinit_subscription_agent go if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSupdatelastsyncinfo') drop procedure sp_MSupdatelastsyncinfo go if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSget_attach_state') drop procedure sp_MSget_attach_state go if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSreset_attach_state') drop procedure sp_MSreset_attach_state go if exists (select * from sysobjects where type = 'P' and name = 'sp_replicationdboption') drop procedure sp_replicationdboption if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSset_subscription_properties') drop procedure sp_MSset_subscription_properties go if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSset_sub_guid') drop procedure sp_MSset_sub_guid go if exists (select * from sysobjects where type = 'P' and name = 'sp_populateqtraninfo') drop procedure sp_populateqtraninfo go if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSscript_trigger_version_updates') drop procedure sp_MSscript_trigger_version_updates go if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSget_load_hint') drop procedure sp_MSget_load_hint go if exists (select * from sysobjects where type in ('P ') and name = 'sp_repladdcolumn') drop procedure sp_repladdcolumn go if exists (select * from sysobjects where type in ('P ') and name = 'sp_MSverifytranfilter') drop procedure sp_MSverifytranfilter go if exists (select * from sysobjects where type in ('P ') and name = 'sp_repldropcolumn') drop procedure sp_repldropcolumn go if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSrepl_validate_dts_package') drop procedure sp_MSrepl_validate_dts_package go if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSagent_access_check') drop procedure sp_MSagent_access_check go if exists (select * from sysobjects where type = 'P ' and name = 'sp_enableagentoffload') drop procedure sp_enableagentoffload go if exists (select * from sysobjects where type = 'P ' and name = 'sp_disableagentoffload') drop procedure sp_disableagentoffload go if exists (select * from sysobjects where type = 'P ' and name = 'sp_getagentoffloadinfo') drop procedure sp_getagentoffloadinfo go if exists (select * from sysobjects where type = 'P ' and name = 'sp_copysubscription') drop procedure sp_copysubscription go if exists (select * from sysobjects where type = 'P ' and name = 'sp_attachsubscription') drop procedure sp_attachsubscription go if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSget_file_existence') drop procedure sp_MSget_file_existence go if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSrestore_sub') drop procedure sp_MSrestore_sub go if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSrestore_sub_tran') drop procedure sp_MSrestore_sub_tran go if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSrestore_sub_merge') drop procedure sp_MSrestore_sub_merge go if exists (select * from sysobjects where type = 'P' and name = 'sp_MSsub_check_identity') drop procedure sp_MSsub_check_identity go if exists (select * from sysobjects where type = 'P' and name = 'sp_MSsub_cleanup_orphans') drop procedure sp_MSsub_cleanup_orphans go if exists (select * from sysobjects where type = 'P' and name = 'sp_MSsub_cleanup_prop_table') drop procedure sp_MSsub_cleanup_prop_table go if exists (select * from sysobjects where type = 'P' and name = 'sp_MSreseed') drop procedure sp_MSreseed go if exists (select * from sysobjects where type = 'P' and name = 'sp_MSsub_set_identity') drop procedure sp_MSsub_set_identity go if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSprepare_sub_for_detach') drop procedure sp_MSprepare_sub_for_detach go if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSadd_compensating_cmd') drop procedure sp_MSadd_compensating_cmd go if exists (select * from sysobjects where type = 'FN' and name = 'fn_varbintohexstr') drop function fn_varbintohexstr go if exists (select * from sysobjects where type = 'FN' and name = 'fn_varbintohexsubstring') drop function fn_varbintohexsubstring go if exists ( select * from sysobjects where type = 'FN' and name = 'fn_MSsharedversion' ) drop function fn_MSsharedversion go if exists ( select * from sysobjects where type = 'P' and name = 'sp_MSgettools_path' ) drop procedure sp_MSgettools_path go if exists ( select * from sysobjects where type = 'P' and name = 'sp_MSget_setup_paths' ) drop procedure sp_MSget_setup_paths go if exists (select * from sysobjects where name = 'sp_MSaddoffloadparameter' and type = 'P') drop procedure sp_MSaddoffloadparameter if exists (select * from sysobjects where name = 'sp_MSremoveoffloadparameter' and type = 'P') drop procedure sp_MSremoveoffloadparameter go if exists (select * from sysobjects where name = 'sp_MSsendtosqlqueue' and type = 'P') drop procedure sp_MSsendtosqlqueue go if exists (select * from sysobjects where type = 'P' and name = 'sp_MSdropfkreferencingarticle') drop procedure sp_MSdropfkreferencingarticle go if exists (select * from sysobjects where type = 'FN' and name = 'fn_MSgensqescstr') drop function fn_MSgensqescstr go if exists (select * from sysobjects where type = 'P' and name = 'sp_MSestimatesnapshotworkload') drop procedure sp_MSestimatesnapshotworkload go if exists (select * from sysobjects where type = 'P' and name = 'sp_MSestimatemergesnapshotworkload') drop procedure sp_MSestimatemergesnapshotworkload go if exists (select * from sysobjects where type = 'P' and name = 'sp_resyncmergesubscription') drop procedure sp_resyncmergesubscription go if exists (select * from sysobjects where type = 'P' and name = 'sp_MSinstance_qv') drop procedure sp_MSinstance_qv if exists (select * from sysobjects where type = 'P' and name = 'sp_MSget_shared_agent') drop procedure sp_MSget_shared_agent if exists (select * from sysobjects where type = 'P' and name = 'sp_MSgetlastupdatedtime') drop procedure sp_MSgetlastupdatedtime if exists (select * from sysobjects where type = 'P' and name = 'sp_MSgettranlastupdatedtime') drop procedure sp_MSgettranlastupdatedtime if exists (select * from sysobjects where type = 'P' and name = 'sp_MSgetmergelastupdatedtime') drop procedure sp_MSgetmergelastupdatedtime go if exists (select * from sysobjects where type = 'P' and name = 'sp_MSrepl_backup_start') drop procedure sp_MSrepl_backup_start go if exists (select * from sysobjects where type = 'P' and name = 'sp_MSrepl_backup_complete') drop procedure sp_MSrepl_backup_complete go if exists (select * from sysobjects where type = 'P' and name = 'sp_MSreplcheckoffloadserver') drop procedure sp_MSreplcheckoffloadserver if exists ( select * from sysobjects where type = 'P ' and name = 'sp_addscriptexec' ) drop procedure sp_addscriptexec if exists ( select * from sysobjects where type = 'P ' and name = 'sp_MSmergeupdatelastsyncinfo' ) drop procedure sp_MSmergeupdatelastsyncinfo go if exists ( select * from sysobjects where type = 'P ' and name = 'sp_MSdroparticleconstraints' ) drop procedure sp_MSdroparticleconstraints go if exists ( select * from sysobjects where type = 'FN' and name = 'fn_replquotename' ) drop function system_function_schema.fn_replquotename if exists ( select * from sysobjects where type = 'FN' and name = 'fn_repladjustcolumnmap' ) drop function system_function_schema.fn_repladjustcolumnmap if exists ( select * from sysobjects where type = 'FN' and name = 'fn_generateparameterpattern' ) drop function system_function_schema.fn_generateparameterpattern if exists ( select * from sysobjects where type = 'FN' and name = 'fn_removeparameterwithargument' ) drop function system_function_schema.fn_removeparameterwithargument if exists ( select * from sysobjects where type = 'FN' and name = 'fn_updateparameterwithargument' ) drop function system_function_schema.fn_updateparameterwithargument if exists ( select * from sysobjects where type = 'FN' and name = 'fn_skipparameterargument' ) drop function system_function_schema.fn_skipparameterargument if exists ( select * from sysobjects where type = 'FN' and name = 'fn_chariswhitespace' ) drop function system_function_schema.fn_chariswhitespace if exists ( select * from sysobjects where type = 'FN' and name = 'fn_replmakestringliteral' ) drop function system_function_schema.fn_replmakestringliteral if exists ( select * from sysobjects where type = 'FN' and name = 'fn_replprepadbinary8' ) drop function system_function_schema.fn_replprepadbinary8 if exists ( select * from sysobjects where type = 'FN' and name = 'fn_replgetbinary8lodword' ) drop function system_function_schema.fn_replgetbinary8lodword if exists ( select * from sysobjects where type = 'P' and name = 'sp_MSacquireserverresourcefordynamicsnapshot') drop procedure sp_MSacquireserverresourcefordynamicsnapshot if exists ( select * from sysobjects where type = 'FN' and name = 'fn_repluniquename' ) drop function system_function_schema.fn_repluniquename if exists (select * from sysobjects where type = 'P' and name = 'sp_MSsetcontext_replagent') drop procedure sp_MSsetcontext_replagent if exists ( select * from sysobjects where type = 'FN' and name = 'fn_isreplmergeagent' ) drop function dbo.fn_isreplmergeagent if exists (select * from sysobjects where type = 'FN' and name = N'fn_replinttobitstring' ) drop function system_function_schema.fn_replinttobitstring if exists (select * from sysobjects where type = 'FN' and name = N'fn_replbitstringtoint' ) drop function system_function_schema.fn_replbitstringtoint if exists (select * from sysobjects where type = 'FN' and name = N'fn_replrotr' ) drop function system_function_schema.fn_replrotr if exists (select * from sysobjects where type = 'FN' and name = N'fn_replgenerateshorterfilenameprefix' ) drop function system_function_schema.fn_replgenerateshorterfilenameprefix if exists (select * from sysobjects where type = 'FN' and name = N'fn_replcomposepublicationsnapshotfolder' ) drop function system_function_schema.fn_replcomposepublicationsnapshotfolder if exists (select * from sysobjects where type = 'FN' and name = N'fn_repltrimleadingzerosinhexstr' ) drop function system_function_schema.fn_repltrimleadingzerosinhexstr if exists (select * from sysobjects where type = 'FN' and name = N'fn_escapecmdshellsymbols' ) drop function system_function_schema.fn_escapecmdshellsymbols if exists (select * from sysobjects where type = 'FN' and name = N'fn_escapecmdshellsymbolsremovequotes' ) drop function system_function_schema.fn_escapecmdshellsymbolsremovequotes if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSispulldistributionjobnamegenerated') drop procedure dbo.sp_MSispulldistributionjobnamegenerated if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSispullmergejobnamegenerated') drop procedure dbo.sp_MSispullmergejobnamegenerated go if exists (select * from sysobjects where type = 'P' and name = 'sp_createmergepalrole') drop procedure sp_createmergepalrole go if exists (select * from sysobjects where type = 'P' and name = 'sp_MSrepl_FixPALRole') drop procedure sp_MSrepl_FixPALRole go if exists (select * from sysobjects where type = 'X' and name = 'xp_execresultset') begin execute dbo.sp_dropextendedproc 'xp_execresultset' end go if exists (select * from sysobjects where type = 'P' and name = 'xp_execresultset') begin drop procedure dbo.xp_execresultset end go if exists (select * from sysobjects where type = 'P' and name = 'sp_execresultset') begin drop procedure dbo.sp_execresultset end go use master go IF EXISTS ( SELECT * FROM sysobjects WHERE uid = USER_ID('system_function_schema') AND name = 'fn_serverid' ) DROP FUNCTION system_function_schema.fn_serverid go sp_addextendedproc 'xp_mergexpusage', 'xprepl.dll' go grant exec on xp_mergexpusage to public go if exists (select * from sysobjects where name = 'xp_showlineage') execute dbo.sp_dropextendedproc 'xp_showlineage' go sp_addextendedproc 'xp_showlineage', 'xprepl.dll' go grant exec on xp_showlineage to public go if exists (select * from sysobjects where name = 'xp_mergelineages' and xtype = 'X') execute dbo.sp_dropextendedproc 'xp_mergelineages' go sp_addextendedproc 'xp_mergelineages', 'xprepl.dll' go if exists (select * from sysobjects where name = 'xp_updatelineage' and xtype = 'X') execute dbo.sp_dropextendedproc 'xp_updatelineage' go if exists (select * from sysobjects where name = 'xp_mapdown_bitmap') execute dbo.sp_dropextendedproc 'xp_mapdown_bitmap' go sp_addextendedproc 'xp_mapdown_bitmap', 'xprepl.dll' go grant exec on xp_mapdown_bitmap to public go if exists (select * from sysobjects where name = 'xp_ORbitmap') execute dbo.sp_dropextendedproc 'xp_ORbitmap' go sp_addextendedproc 'xp_ORbitmap', 'xprepl.dll' go if exists (select * from sysobjects where name = 'xp_proxiedmetadata') execute dbo.sp_dropextendedproc 'xp_proxiedmetadata' go sp_addextendedproc 'xp_proxiedmetadata', 'xprepl.dll' go if exists (select * from sysobjects where name = 'xp_initcolvs' and xtype = 'X') execute dbo.sp_dropextendedproc 'xp_initcolvs' go if exists (select * from sysobjects where name = 'xp_updatecolvbm' and xtype = 'X') execute dbo.sp_dropextendedproc 'xp_updatecolvbm' go if exists (select * from sysobjects where name = 'xp_showcolv') execute dbo.sp_dropextendedproc 'xp_showcolv' go sp_addextendedproc 'xp_showcolv', 'xprepl.dll' go grant exec on xp_showcolv to public go if exists (select * from sysobjects where name = 'xp_varbintohexstr') execute dbo.sp_dropextendedproc 'xp_varbintohexstr' go sp_addextendedproc 'xp_varbintohexstr', 'xprepl.dll' go if exists (select * from sysobjects where name = 'xp_intersectbitmaps') execute dbo.sp_dropextendedproc 'xp_intersectbitmaps' go if exists (select * from sysobjects where name = 'xp_displayparamstmt') execute dbo.sp_dropextendedproc 'xp_displayparamstmt' go sp_addextendedproc 'xp_displayparamstmt', 'xprepl.dll' go if exists (select * from sysobjects where name = 'xp_printstatements') execute dbo.sp_dropextendedproc 'xp_printstatements' go sp_addextendedproc 'xp_printstatements', 'xprepl.dll' go if exists (select * from sysobjects where name = 'xp_createqueue') execute dbo.sp_dropextendedproc 'xp_createqueue' go if exists (select * from sysobjects where name = 'xp_createprivatequeue') execute dbo.sp_dropextendedproc 'xp_createprivatequeue' exec sp_addextendedproc 'xp_createprivatequeue', 'xpqueue.dll' go if exists (select * from sysobjects where name = 'xp_deletequeue') execute dbo.sp_dropextendedproc 'xp_deletequeue' go if exists (select * from sysobjects where name = 'xp_deleteprivatequeue') execute dbo.sp_dropextendedproc 'xp_deleteprivatequeue' exec sp_addextendedproc 'xp_deleteprivatequeue', 'xpqueue.dll' go if exists (select * from sysobjects where name = 'sp_replsendtoqueue') execute dbo.sp_dropextendedproc 'sp_replsendtoqueue' go sp_addextendedproc 'sp_replsendtoqueue', 'sp_replsendtoqueue extended proc' go grant exec on sp_replsendtoqueue to public go if exists (select * from sysobjects where name = 'sp_replwritetovarbin') execute dbo.sp_dropextendedproc 'sp_replwritetovarbin' go sp_addextendedproc 'sp_replwritetovarbin', 'sp_replwritetovarbin extended proc' go grant exec on sp_replwritetovarbin to public go if exists (select * from sysobjects where name = 'xp_resetqueue') execute dbo.sp_dropextendedproc 'xp_resetqueue' go sp_addextendedproc 'xp_resetqueue', 'xpqueue.dll' go if exists (select * from sysobjects where name = 'xp_peekqueue') execute dbo.sp_dropextendedproc 'xp_peekqueue' go sp_addextendedproc 'xp_peekqueue', 'xpqueue.dll' go if exists (select * from sysobjects where name = 'xp_controlqueueservice') execute dbo.sp_dropextendedproc 'xp_controlqueueservice' go sp_addextendedproc 'xp_controlqueueservice', 'xpqueue.dll' go if exists (select * from sysobjects where name = 'xp_displayqueuemesgs') execute dbo.sp_dropextendedproc 'xp_displayqueuemesgs' go sp_addextendedproc 'xp_displayqueuemesgs', 'xpqueue.dll' go if exists (select * from sysobjects where name = 'xp_decodequeuecmd') execute dbo.sp_dropextendedproc 'xp_decodequeuecmd' go sp_addextendedproc 'xp_decodequeuecmd', 'xpqueue.dll' go if exists (select * from sysobjects where name = 'xp_readpkfromqueue') execute dbo.sp_dropextendedproc 'xp_readpkfromqueue' go sp_addextendedproc 'xp_readpkfromqueue', 'xpqueue.dll' go if exists (select * from sysobjects where name = 'xp_readpkfromvarbin') execute dbo.sp_dropextendedproc 'xp_readpkfromvarbin' go sp_addextendedproc 'xp_readpkfromvarbin', 'xpqueue.dll' go /* ** Add xp_makecab extended procedure */ if exists (select * from sysobjects where type = 'X' and name = 'xp_makecab') exec dbo.sp_dropextendedproc 'xp_makecab' go sp_addextendedproc 'xp_makecab', 'xprepl.dll' go exec dbo.sp_MS_marksystemobject xp_makecab go /* ** Add xp_unpackcab extended procedure */ if exists (select * from sysobjects where type = 'X' and name = 'xp_unpackcab') exec dbo.sp_dropextendedproc 'xp_unpackcab' go sp_addextendedproc 'xp_unpackcab', 'xprepl.dll' go exec dbo.sp_MS_marksystemobject xp_unpackcab go /* Create table dbo.MSreplication_options */ IF NOT EXISTS (SELECT * FROM sysobjects WHERE name = 'MSreplication_options' and type = 'U') BEGIN raiserror('Creating procedure Creating table MSreplication_options',0,1) CREATE TABLE dbo.MSreplication_options ( optname sysname NOT NULL, value bit NOT NULL, major_version int NOT NULL, minor_version int NOT NULL, revision int NOT NULL, install_failures int NOT NULL ) END GO IF NOT EXISTS (SELECT * FROM MSreplication_options WHERE optname = 'transactional') INSERT INTO MSreplication_options VALUES ('transactional',0,0,0,0,0) IF NOT EXISTS (SELECT * FROM MSreplication_options WHERE optname = 'merge') INSERT INTO MSreplication_options VALUES ('merge',0,0,0,0,0) GO -- -- Name: -- xp_execresultset -- -- Description: -- This is a wrapper proc to sp_execresultset and provides us -- with the ability to change user database context based on -- the @dbname provided. -- -- Parameters: -- (see create call below) -- -- Result: -- -- Returns -- 0 - succeeded -- 1 - failed -- -- Security: -- Sysadmin & DBO access only -- raiserror('Creating procedure xp_execresultset', 0,1) with nowait go create procedure dbo.xp_execresultset ( @cmd nvarchar(4000), @dbname sysname = NULL, @debug bit = 0 ) as begin declare @retcode bit, @proc nvarchar(4000) -- check to ensure that the @dbname provided is neither null or empty if isnull(rtrim(@dbname), N'') = N'' begin raiserror('Internal Error : @dbname cannot be null or empty.', 16, -1) return 1 end select @proc = quotename(@dbname) + N'.dbo.sp_execresultset' exec @retcode = @proc @cmd, @debug return @retcode end go -- -- Name: -- sp_execresultset -- -- Description: -- This procedure replaces the extended stored procedure xp_execresultset. -- The proc accepts a query (@cmd) and builds a buffer with the queries -- resultset and executes it against the current database. This proc has -- a ~1MB limit on the resultset text that can be executed. -- -- Parameters: -- (see create call below) -- -- Result: -- -- Returns -- 0 - succeeded -- 1 - failed -- -- Security: -- Sysadmin & DBO access only -- raiserror('Creating procedure sp_execresultset', 0,1) with nowait go create procedure dbo.sp_execresultset ( @cmd nvarchar(4000), -- Command that will return a resultset to concat and execute @debug bit = 0 -- Display debug information and resultset query (no exec) ) as begin set nocount on declare @MAXBUFFLEN int, @qPosition int, @qValue nvarchar(4000), @scriptLen int, @scriptText nvarchar(4000), @maxIndex bigint, @rowIndex bigint -- declare 250 nvarchar(4000) (nearly 1MB worth of space) declare @q1 nvarchar(4000), @q2 nvarchar(4000), @q3 nvarchar(4000), @q4 nvarchar(4000), @q5 nvarchar(4000), @q6 nvarchar(4000), @q7 nvarchar(4000), @q8 nvarchar(4000), @q9 nvarchar(4000), @q10 nvarchar(4000), @q11 nvarchar(4000), @q12 nvarchar(4000), @q13 nvarchar(4000), @q14 nvarchar(4000), @q15 nvarchar(4000), @q16 nvarchar(4000), @q17 nvarchar(4000), @q18 nvarchar(4000), @q19 nvarchar(4000), @q20 nvarchar(4000), @q21 nvarchar(4000), @q22 nvarchar(4000), @q23 nvarchar(4000), @q24 nvarchar(4000), @q25 nvarchar(4000), @q26 nvarchar(4000), @q27 nvarchar(4000), @q28 nvarchar(4000), @q29 nvarchar(4000), @q30 nvarchar(4000), @q31 nvarchar(4000), @q32 nvarchar(4000), @q33 nvarchar(4000), @q34 nvarchar(4000), @q35 nvarchar(4000), @q36 nvarchar(4000), @q37 nvarchar(4000), @q38 nvarchar(4000), @q39 nvarchar(4000), @q40 nvarchar(4000), @q41 nvarchar(4000), @q42 nvarchar(4000), @q43 nvarchar(4000), @q44 nvarchar(4000), @q45 nvarchar(4000), @q46 nvarchar(4000), @q47 nvarchar(4000), @q48 nvarchar(4000), @q49 nvarchar(4000), @q50 nvarchar(4000), @q51 nvarchar(4000), @q52 nvarchar(4000), @q53 nvarchar(4000), @q54 nvarchar(4000), @q55 nvarchar(4000), @q56 nvarchar(4000), @q57 nvarchar(4000), @q58 nvarchar(4000), @q59 nvarchar(4000), @q60 nvarchar(4000), @q61 nvarchar(4000), @q62 nvarchar(4000), @q63 nvarchar(4000), @q64 nvarchar(4000), @q65 nvarchar(4000), @q66 nvarchar(4000), @q67 nvarchar(4000), @q68 nvarchar(4000), @q69 nvarchar(4000), @q70 nvarchar(4000), @q71 nvarchar(4000), @q72 nvarchar(4000), @q73 nvarchar(4000), @q74 nvarchar(4000), @q75 nvarchar(4000), @q76 nvarchar(4000), @q77 nvarchar(4000), @q78 nvarchar(4000), @q79 nvarchar(4000), @q80 nvarchar(4000), @q81 nvarchar(4000), @q82 nvarchar(4000), @q83 nvarchar(4000), @q84 nvarchar(4000), @q85 nvarchar(4000), @q86 nvarchar(4000), @q87 nvarchar(4000), @q88 nvarchar(4000), @q89 nvarchar(4000), @q90 nvarchar(4000), @q91 nvarchar(4000), @q92 nvarchar(4000), @q93 nvarchar(4000), @q94 nvarchar(4000), @q95 nvarchar(4000), @q96 nvarchar(4000), @q97 nvarchar(4000), @q98 nvarchar(4000), @q99 nvarchar(4000), @q100 nvarchar(4000), @q101 nvarchar(4000), @q102 nvarchar(4000), @q103 nvarchar(4000), @q104 nvarchar(4000), @q105 nvarchar(4000), @q106 nvarchar(4000), @q107 nvarchar(4000), @q108 nvarchar(4000), @q109 nvarchar(4000), @q110 nvarchar(4000), @q111 nvarchar(4000), @q112 nvarchar(4000), @q113 nvarchar(4000), @q114 nvarchar(4000), @q115 nvarchar(4000), @q116 nvarchar(4000), @q117 nvarchar(4000), @q118 nvarchar(4000), @q119 nvarchar(4000), @q120 nvarchar(4000), @q121 nvarchar(4000), @q122 nvarchar(4000), @q123 nvarchar(4000), @q124 nvarchar(4000), @q125 nvarchar(4000), @q126 nvarchar(4000), @q127 nvarchar(4000), @q128 nvarchar(4000), @q129 nvarchar(4000), @q130 nvarchar(4000), @q131 nvarchar(4000), @q132 nvarchar(4000), @q133 nvarchar(4000), @q134 nvarchar(4000), @q135 nvarchar(4000), @q136 nvarchar(4000), @q137 nvarchar(4000), @q138 nvarchar(4000), @q139 nvarchar(4000), @q140 nvarchar(4000), @q141 nvarchar(4000), @q142 nvarchar(4000), @q143 nvarchar(4000), @q144 nvarchar(4000), @q145 nvarchar(4000), @q146 nvarchar(4000), @q147 nvarchar(4000), @q148 nvarchar(4000), @q149 nvarchar(4000), @q150 nvarchar(4000), @q151 nvarchar(4000), @q152 nvarchar(4000), @q153 nvarchar(4000), @q154 nvarchar(4000), @q155 nvarchar(4000), @q156 nvarchar(4000), @q157 nvarchar(4000), @q158 nvarchar(4000), @q159 nvarchar(4000), @q160 nvarchar(4000), @q161 nvarchar(4000), @q162 nvarchar(4000), @q163 nvarchar(4000), @q164 nvarchar(4000), @q165 nvarchar(4000), @q166 nvarchar(4000), @q167 nvarchar(4000), @q168 nvarchar(4000), @q169 nvarchar(4000), @q170 nvarchar(4000), @q171 nvarchar(4000), @q172 nvarchar(4000), @q173 nvarchar(4000), @q174 nvarchar(4000), @q175 nvarchar(4000), @q176 nvarchar(4000), @q177 nvarchar(4000), @q178 nvarchar(4000), @q179 nvarchar(4000), @q180 nvarchar(4000), @q181 nvarchar(4000), @q182 nvarchar(4000), @q183 nvarchar(4000), @q184 nvarchar(4000), @q185 nvarchar(4000), @q186 nvarchar(4000), @q187 nvarchar(4000), @q188 nvarchar(4000), @q189 nvarchar(4000), @q190 nvarchar(4000), @q191 nvarchar(4000), @q192 nvarchar(4000), @q193 nvarchar(4000), @q194 nvarchar(4000), @q195 nvarchar(4000), @q196 nvarchar(4000), @q197 nvarchar(4000), @q198 nvarchar(4000), @q199 nvarchar(4000), @q200 nvarchar(4000), @q201 nvarchar(4000), @q202 nvarchar(4000), @q203 nvarchar(4000), @q204 nvarchar(4000), @q205 nvarchar(4000), @q206 nvarchar(4000), @q207 nvarchar(4000), @q208 nvarchar(4000), @q209 nvarchar(4000), @q210 nvarchar(4000), @q211 nvarchar(4000), @q212 nvarchar(4000), @q213 nvarchar(4000), @q214 nvarchar(4000), @q215 nvarchar(4000), @q216 nvarchar(4000), @q217 nvarchar(4000), @q218 nvarchar(4000), @q219 nvarchar(4000), @q220 nvarchar(4000), @q221 nvarchar(4000), @q222 nvarchar(4000), @q223 nvarchar(4000), @q224 nvarchar(4000), @q225 nvarchar(4000), @q226 nvarchar(4000), @q227 nvarchar(4000), @q228 nvarchar(4000), @q229 nvarchar(4000), @q230 nvarchar(4000), @q231 nvarchar(4000), @q232 nvarchar(4000), @q233 nvarchar(4000), @q234 nvarchar(4000), @q235 nvarchar(4000), @q236 nvarchar(4000), @q237 nvarchar(4000), @q238 nvarchar(4000), @q239 nvarchar(4000), @q240 nvarchar(4000), @q241 nvarchar(4000), @q242 nvarchar(4000), @q243 nvarchar(4000), @q244 nvarchar(4000), @q245 nvarchar(4000), @q246 nvarchar(4000), @q247 nvarchar(4000), @q248 nvarchar(4000), @q249 nvarchar(4000), @q250 nvarchar(4000) -- initialize all vars select @q1 = N'', @q2 = N'', @q3 = N'', @q4 = N'', @q5 = N'', @q6 = N'', @q7 = N'', @q8 = N'', @q9 = N'', @q10 = N'', @q11 = N'', @q12 = N'', @q13 = N'', @q14 = N'', @q15 = N'', @q16 = N'', @q17 = N'', @q18 = N'', @q19 = N'', @q20 = N'', @q21 = N'', @q22 = N'', @q23 = N'', @q24 = N'', @q25 = N'', @q26 = N'', @q27 = N'', @q28 = N'', @q29 = N'', @q30 = N'', @q31 = N'', @q32 = N'', @q33 = N'', @q34 = N'', @q35 = N'', @q36 = N'', @q37 = N'', @q38 = N'', @q39 = N'', @q40 = N'', @q41 = N'', @q42 = N'', @q43 = N'', @q44 = N'', @q45 = N'', @q46 = N'', @q47 = N'', @q48 = N'', @q49 = N'', @q50 = N'', @q51 = N'', @q52 = N'', @q53 = N'', @q54 = N'', @q55 = N'', @q56 = N'', @q57 = N'', @q58 = N'', @q59 = N'', @q60 = N'', @q61 = N'', @q62 = N'', @q63 = N'', @q64 = N'', @q65 = N'', @q66 = N'', @q67 = N'', @q68 = N'', @q69 = N'', @q70 = N'', @q71 = N'', @q72 = N'', @q73 = N'', @q74 = N'', @q75 = N'', @q76 = N'', @q77 = N'', @q78 = N'', @q79 = N'', @q80 = N'', @q81 = N'', @q82 = N'', @q83 = N'', @q84 = N'', @q85 = N'', @q86 = N'', @q87 = N'', @q88 = N'', @q89 = N'', @q90 = N'', @q91 = N'', @q92 = N'', @q93 = N'', @q94 = N'', @q95 = N'', @q96 = N'', @q97 = N'', @q98 = N'', @q99 = N'', @q100 = N'', @q101 = N'', @q102 = N'', @q103 = N'', @q104 = N'', @q105 = N'', @q106 = N'', @q107 = N'', @q108 = N'', @q109 = N'', @q110 = N'', @q111 = N'', @q112 = N'', @q113 = N'', @q114 = N'', @q115 = N'', @q116 = N'', @q117 = N'', @q118 = N'', @q119 = N'', @q120 = N'', @q121 = N'', @q122 = N'', @q123 = N'', @q124 = N'', @q125 = N'', @q126 = N'', @q127 = N'', @q128 = N'', @q129 = N'', @q130 = N'', @q131 = N'', @q132 = N'', @q133 = N'', @q134 = N'', @q135 = N'', @q136 = N'', @q137 = N'', @q138 = N'', @q139 = N'', @q140 = N'', @q141 = N'', @q142 = N'', @q143 = N'', @q144 = N'', @q145 = N'', @q146 = N'', @q147 = N'', @q148 = N'', @q149 = N'', @q150 = N'', @q151 = N'', @q152 = N'', @q153 = N'', @q154 = N'', @q155 = N'', @q156 = N'', @q157 = N'', @q158 = N'', @q159 = N'', @q160 = N'', @q161 = N'', @q162 = N'', @q163 = N'', @q164 = N'', @q165 = N'', @q166 = N'', @q167 = N'', @q168 = N'', @q169 = N'', @q170 = N'', @q171 = N'', @q172 = N'', @q173 = N'', @q174 = N'', @q175 = N'', @q176 = N'', @q177 = N'', @q178 = N'', @q179 = N'', @q180 = N'', @q181 = N'', @q182 = N'', @q183 = N'', @q184 = N'', @q185 = N'', @q186 = N'', @q187 = N'', @q188 = N'', @q189 = N'', @q190 = N'', @q191 = N'', @q192 = N'', @q193 = N'', @q194 = N'', @q195 = N'', @q196 = N'', @q197 = N'', @q198 = N'', @q199 = N'', @q200 = N'', @q201 = N'', @q202 = N'', @q203 = N'', @q204 = N'', @q205 = N'', @q206 = N'', @q207 = N'', @q208 = N'', @q209 = N'', @q210 = N'', @q211 = N'', @q212 = N'', @q213 = N'', @q214 = N'', @q215 = N'', @q216 = N'', @q217 = N'', @q218 = N'', @q219 = N'', @q220 = N'', @q221 = N'', @q222 = N'', @q223 = N'', @q224 = N'', @q225 = N'', @q226 = N'', @q227 = N'', @q228 = N'', @q229 = N'', @q230 = N'', @q231 = N'', @q232 = N'', @q233 = N'', @q234 = N'', @q235 = N'', @q236 = N'', @q237 = N'', @q238 = N'', @q239 = N'', @q240 = N'', @q241 = N'', @q242 = N'', @q243 = N'', @q244 = N'', @q245 = N'', @q246 = N'', @q247 = N'', @q248 = N'', @q249 = N'', @q250 = N'' select @MAXBUFFLEN = 4000, @qPosition = 1, @qValue = N'', @scriptLen = 0, @scriptText = N'' -- check if our scripting table exists, if so let's drop it if object_id('tempdb..#MSrepl_exec_script', 'U') is not null begin drop table #MSrepl_exec_script end -- create and load a local tmp table with the resultset based off of the cmd provided create table #MSrepl_exec_script (orderCol int identity(1,1) primary key clustered, scriptText nvarchar(4000)) if @@error <> 0 begin goto Error end insert into #MSrepl_exec_script(scriptText) exec(@cmd) if @@error <> 0 begin goto Error end -- get the max value inserted in the identity col for -- #MSrepl_exec_script table and set the rowIndex = 1 select @maxIndex = max(orderCol), @rowIndex = 1 from #MSrepl_exec_script -- retrieve the current scriptText row select @scriptText = isnull(scriptText, N'') from #MSrepl_exec_script where orderCol = @rowIndex while (@rowIndex <= @maxIndex) begin select @scriptLen = @scriptLen + datalength(@scriptText)/2 if (@scriptLen < @MAXBUFFLEN) begin -- for this case we continue to append since we know we have room select @qValue = @qValue + @scriptText + N' ' -- add one to the script length for the space we just added select @scriptLen = @scriptLen + 1 -- increment the row position counter select @rowIndex = @rowIndex + 1 -- retrieve the current scriptText row select @scriptText = isnull(scriptText, N'') from #MSrepl_exec_script where orderCol = @rowIndex -- If there are no more script pieces then we will not continue -- instead we will set the current @qPosition and the loop will exit -- -- Also be sure that if we reach the MAXBUFFLEN at this point we do not -- continue. Instead we want to set the value below first before we continue. -- FYI: It will never be possible to be greater than MAXBUFFLEN in this section. if(@rowIndex <= @maxIndex and @scriptLen != @MAXBUFFLEN) begin continue end end else if (@scriptLen > @MAXBUFFLEN) begin -- here we have exceeded the @MAXBUFFLEN char limit so we will -- fill the @qValue buffer and then store off the remaining -- scriptText to be appended on the next itteration of the loop select @qValue = @qValue + left(@scriptText, @MAXBUFFLEN - datalength(@qValue)/2) select @scriptText = right(@scriptText, @scriptLen - @MAXBUFFLEN) end else begin -- Append the entire scriptText since we know we have room. Do not -- add the command seperator (space) since there is no room for that select @qValue = @qValue + @scriptText -- set the scripttext to empty so that on the next loop -- we will add a space to the first qPostition buffer select @scriptText = N'' end -- set one of the 250 vars -- we need to break this 'else if' list by 100 because there is a limit of nesting levels -- this is a good idea in any case because it should speed things up a bit if @qPosition <= 100 begin if @qPosition = 1 select @q1 = @qValue else if @qPosition = 2 select @q2 = @qValue else if @qPosition = 3 select @q3 = @qValue else if @qPosition = 4 select @q4 = @qValue else if @qPosition = 5 select @q5 = @qValue else if @qPosition = 6 select @q6 = @qValue else if @qPosition = 7 select @q7 = @qValue else if @qPosition = 8 select @q8 = @qValue else if @qPosition = 9 select @q9 = @qValue else if @qPosition = 10 select @q10 = @qValue else if @qPosition = 11 select @q11 = @qValue else if @qPosition = 12 select @q12 = @qValue else if @qPosition = 13 select @q13 = @qValue else if @qPosition = 14 select @q14 = @qValue else if @qPosition = 15 select @q15 = @qValue else if @qPosition = 16 select @q16 = @qValue else if @qPosition = 17 select @q17 = @qValue else if @qPosition = 18 select @q18 = @qValue else if @qPosition = 19 select @q19 = @qValue else if @qPosition = 20 select @q20 = @qValue else if @qPosition = 21 select @q21 = @qValue else if @qPosition = 22 select @q22 = @qValue else if @qPosition = 23 select @q23 = @qValue else if @qPosition = 24 select @q24 = @qValue else if @qPosition = 25 select @q25 = @qValue else if @qPosition = 26 select @q26 = @qValue else if @qPosition = 27 select @q27 = @qValue else if @qPosition = 28 select @q28 = @qValue else if @qPosition = 29 select @q29 = @qValue else if @qPosition = 30 select @q30 = @qValue else if @qPosition = 31 select @q31 = @qValue else if @qPosition = 32 select @q32 = @qValue else if @qPosition = 33 select @q33 = @qValue else if @qPosition = 34 select @q34 = @qValue else if @qPosition = 35 select @q35 = @qValue else if @qPosition = 36 select @q36 = @qValue else if @qPosition = 37 select @q37 = @qValue else if @qPosition = 38 select @q38 = @qValue else if @qPosition = 39 select @q39 = @qValue else if @qPosition = 40 select @q40 = @qValue else if @qPosition = 41 select @q41 = @qValue else if @qPosition = 42 select @q42 = @qValue else if @qPosition = 43 select @q43 = @qValue else if @qPosition = 44 select @q44 = @qValue else if @qPosition = 45 select @q45 = @qValue else if @qPosition = 46 select @q46 = @qValue else if @qPosition = 47 select @q47 = @qValue else if @qPosition = 48 select @q48 = @qValue else if @qPosition = 49 select @q49 = @qValue else if @qPosition = 50 select @q50 = @qValue else if @qPosition = 51 select @q51 = @qValue else if @qPosition = 52 select @q52 = @qValue else if @qPosition = 53 select @q53 = @qValue else if @qPosition = 54 select @q54 = @qValue else if @qPosition = 55 select @q55 = @qValue else if @qPosition = 56 select @q56 = @qValue else if @qPosition = 57 select @q57 = @qValue else if @qPosition = 58 select @q58 = @qValue else if @qPosition = 59 select @q59 = @qValue else if @qPosition = 60 select @q60 = @qValue else if @qPosition = 61 select @q61 = @qValue else if @qPosition = 62 select @q62 = @qValue else if @qPosition = 63 select @q63 = @qValue else if @qPosition = 64 select @q64 = @qValue else if @qPosition = 65 select @q65 = @qValue else if @qPosition = 66 select @q66 = @qValue else if @qPosition = 67 select @q67 = @qValue else if @qPosition = 68 select @q68 = @qValue else if @qPosition = 69 select @q69 = @qValue else if @qPosition = 70 select @q70 = @qValue else if @qPosition = 71 select @q71 = @qValue else if @qPosition = 72 select @q72 = @qValue else if @qPosition = 73 select @q73 = @qValue else if @qPosition = 74 select @q74 = @qValue else if @qPosition = 75 select @q75 = @qValue else if @qPosition = 76 select @q76 = @qValue else if @qPosition = 77 select @q77 = @qValue else if @qPosition = 78 select @q78 = @qValue else if @qPosition = 79 select @q79 = @qValue else if @qPosition = 80 select @q80 = @qValue else if @qPosition = 81 select @q81 = @qValue else if @qPosition = 82 select @q82 = @qValue else if @qPosition = 83 select @q83 = @qValue else if @qPosition = 84 select @q84 = @qValue else if @qPosition = 85 select @q85 = @qValue else if @qPosition = 86 select @q86 = @qValue else if @qPosition = 87 select @q87 = @qValue else if @qPosition = 88 select @q88 = @qValue else if @qPosition = 89 select @q89 = @qValue else if @qPosition = 90 select @q90 = @qValue else if @qPosition = 91 select @q91 = @qValue else if @qPosition = 92 select @q92 = @qValue else if @qPosition = 93 select @q93 = @qValue else if @qPosition = 94 select @q94 = @qValue else if @qPosition = 95 select @q95 = @qValue else if @qPosition = 96 select @q96 = @qValue else if @qPosition = 97 select @q97 = @qValue else if @qPosition = 98 select @q98 = @qValue else if @qPosition = 99 select @q99 = @qValue else if @qPosition = 100 select @q100 = @qValue end else if @qPosition <= 200 begin if @qPosition = 101 select @q101 = @qValue else if @qPosition = 102 select @q102 = @qValue else if @qPosition = 103 select @q103 = @qValue else if @qPosition = 104 select @q104 = @qValue else if @qPosition = 105 select @q105 = @qValue else if @qPosition = 106 select @q106 = @qValue else if @qPosition = 107 select @q107 = @qValue else if @qPosition = 108 select @q108 = @qValue else if @qPosition = 109 select @q109 = @qValue else if @qPosition = 110 select @q110 = @qValue else if @qPosition = 111 select @q111 = @qValue else if @qPosition = 112 select @q112 = @qValue else if @qPosition = 113 select @q113 = @qValue else if @qPosition = 114 select @q114 = @qValue else if @qPosition = 115 select @q115 = @qValue else if @qPosition = 116 select @q116 = @qValue else if @qPosition = 117 select @q117 = @qValue else if @qPosition = 118 select @q118 = @qValue else if @qPosition = 119 select @q119 = @qValue else if @qPosition = 120 select @q120 = @qValue else if @qPosition = 121 select @q121 = @qValue else if @qPosition = 122 select @q122 = @qValue else if @qPosition = 123 select @q123 = @qValue else if @qPosition = 124 select @q124 = @qValue else if @qPosition = 125 select @q125 = @qValue else if @qPosition = 126 select @q126 = @qValue else if @qPosition = 127 select @q127 = @qValue else if @qPosition = 128 select @q128 = @qValue else if @qPosition = 129 select @q129 = @qValue else if @qPosition = 130 select @q130 = @qValue else if @qPosition = 131 select @q131 = @qValue else if @qPosition = 132 select @q132 = @qValue else if @qPosition = 133 select @q133 = @qValue else if @qPosition = 134 select @q134 = @qValue else if @qPosition = 135 select @q135 = @qValue else if @qPosition = 136 select @q136 = @qValue else if @qPosition = 137 select @q137 = @qValue else if @qPosition = 138 select @q138 = @qValue else if @qPosition = 139 select @q139 = @qValue else if @qPosition = 140 select @q140 = @qValue else if @qPosition = 141 select @q141 = @qValue else if @qPosition = 142 select @q142 = @qValue else if @qPosition = 143 select @q143 = @qValue else if @qPosition = 144 select @q144 = @qValue else if @qPosition = 145 select @q145 = @qValue else if @qPosition = 146 select @q146 = @qValue else if @qPosition = 147 select @q147 = @qValue else if @qPosition = 148 select @q148 = @qValue else if @qPosition = 149 select @q149 = @qValue else if @qPosition = 150 select @q150 = @qValue else if @qPosition = 151 select @q151 = @qValue else if @qPosition = 152 select @q152 = @qValue else if @qPosition = 153 select @q153 = @qValue else if @qPosition = 154 select @q154 = @qValue else if @qPosition = 155 select @q155 = @qValue else if @qPosition = 156 select @q156 = @qValue else if @qPosition = 157 select @q157 = @qValue else if @qPosition = 158 select @q158 = @qValue else if @qPosition = 159 select @q159 = @qValue else if @qPosition = 160 select @q160 = @qValue else if @qPosition = 161 select @q161 = @qValue else if @qPosition = 162 select @q162 = @qValue else if @qPosition = 163 select @q163 = @qValue else if @qPosition = 164 select @q164 = @qValue else if @qPosition = 165 select @q165 = @qValue else if @qPosition = 166 select @q166 = @qValue else if @qPosition = 167 select @q167 = @qValue else if @qPosition = 168 select @q168 = @qValue else if @qPosition = 169 select @q169 = @qValue else if @qPosition = 170 select @q170 = @qValue else if @qPosition = 171 select @q171 = @qValue else if @qPosition = 172 select @q172 = @qValue else if @qPosition = 173 select @q173 = @qValue else if @qPosition = 174 select @q174 = @qValue else if @qPosition = 175 select @q175 = @qValue else if @qPosition = 176 select @q176 = @qValue else if @qPosition = 177 select @q177 = @qValue else if @qPosition = 178 select @q178 = @qValue else if @qPosition = 179 select @q179 = @qValue else if @qPosition = 180 select @q180 = @qValue else if @qPosition = 181 select @q181 = @qValue else if @qPosition = 182 select @q182 = @qValue else if @qPosition = 183 select @q183 = @qValue else if @qPosition = 184 select @q184 = @qValue else if @qPosition = 185 select @q185 = @qValue else if @qPosition = 186 select @q186 = @qValue else if @qPosition = 187 select @q187 = @qValue else if @qPosition = 188 select @q188 = @qValue else if @qPosition = 189 select @q189 = @qValue else if @qPosition = 190 select @q190 = @qValue else if @qPosition = 191 select @q191 = @qValue else if @qPosition = 192 select @q192 = @qValue else if @qPosition = 193 select @q193 = @qValue else if @qPosition = 194 select @q194 = @qValue else if @qPosition = 195 select @q195 = @qValue else if @qPosition = 196 select @q196 = @qValue else if @qPosition = 197 select @q197 = @qValue else if @qPosition = 198 select @q198 = @qValue else if @qPosition = 199 select @q199 = @qValue else if @qPosition = 200 select @q200 = @qValue end else begin if @qPosition = 201 select @q201 = @qValue else if @qPosition = 202 select @q202 = @qValue else if @qPosition = 203 select @q203 = @qValue else if @qPosition = 204 select @q204 = @qValue else if @qPosition = 205 select @q205 = @qValue else if @qPosition = 206 select @q206 = @qValue else if @qPosition = 207 select @q207 = @qValue else if @qPosition = 208 select @q208 = @qValue else if @qPosition = 209 select @q209 = @qValue else if @qPosition = 210 select @q210 = @qValue else if @qPosition = 211 select @q211 = @qValue else if @qPosition = 212 select @q212 = @qValue else if @qPosition = 213 select @q213 = @qValue else if @qPosition = 214 select @q214 = @qValue else if @qPosition = 215 select @q215 = @qValue else if @qPosition = 216 select @q216 = @qValue else if @qPosition = 217 select @q217 = @qValue else if @qPosition = 218 select @q218 = @qValue else if @qPosition = 219 select @q219 = @qValue else if @qPosition = 220 select @q220 = @qValue else if @qPosition = 221 select @q221 = @qValue else if @qPosition = 222 select @q222 = @qValue else if @qPosition = 223 select @q223 = @qValue else if @qPosition = 224 select @q224 = @qValue else if @qPosition = 225 select @q225 = @qValue else if @qPosition = 226 select @q226 = @qValue else if @qPosition = 227 select @q227 = @qValue else if @qPosition = 228 select @q228 = @qValue else if @qPosition = 229 select @q229 = @qValue else if @qPosition = 230 select @q230 = @qValue else if @qPosition = 231 select @q231 = @qValue else if @qPosition = 232 select @q232 = @qValue else if @qPosition = 233 select @q233 = @qValue else if @qPosition = 234 select @q234 = @qValue else if @qPosition = 235 select @q235 = @qValue else if @qPosition = 236 select @q236 = @qValue else if @qPosition = 237 select @q237 = @qValue else if @qPosition = 238 select @q238 = @qValue else if @qPosition = 239 select @q239 = @qValue else if @qPosition = 240 select @q240 = @qValue else if @qPosition = 241 select @q241 = @qValue else if @qPosition = 242 select @q242 = @qValue else if @qPosition = 243 select @q243 = @qValue else if @qPosition = 244 select @q244 = @qValue else if @qPosition = 245 select @q245 = @qValue else if @qPosition = 246 select @q246 = @qValue else if @qPosition = 247 select @q247 = @qValue else if @qPosition = 248 select @q248 = @qValue else if @qPosition = 249 select @q249 = @qValue else if @qPosition = 250 select @q250 = @qValue if @qPosition > 250 begin raiserror('Internal Error : Command buffer limit of ~1MB has been reached! Resultset will not be executed.', 16, -1) goto Error end end -- Since we just filled a buffer move the index value by one -- and reset the current query row value to empty and len to 0 select @qPosition = @qPosition + 1, @qValue = N'', @scriptLen = 0 end if @debug = 0 begin -- concat all buffers and execute exec(@q1+@q2+@q3+@q4+@q5+@q6+@q7+@q8+@q9+@q10+ @q11+@q12+@q13+@q14+@q15+@q16+@q17+@q18+@q19+@q20+ @q21+@q22+@q23+@q24+@q25+@q26+@q27+@q28+@q29+@q30+ @q31+@q32+@q33+@q34+@q35+@q36+@q37+@q38+@q39+@q40+ @q41+@q42+@q43+@q44+@q45+@q46+@q47+@q48+@q49+@q50+ @q51+@q52+@q53+@q54+@q55+@q56+@q57+@q58+@q59+@q60+ @q61+@q62+@q63+@q64+@q65+@q66+@q67+@q68+@q69+@q70+ @q71+@q72+@q73+@q74+@q75+@q76+@q77+@q78+@q79+@q80+ @q81+@q82+@q83+@q84+@q85+@q86+@q87+@q88+@q89+@q90+ @q91+@q92+@q93+@q94+@q95+@q96+@q97+@q98+@q99+@q100+ @q101+@q102+@q103+@q104+@q105+@q106+@q107+@q108+@q109+@q110+ @q111+@q112+@q113+@q114+@q115+@q116+@q117+@q118+@q119+@q120+ @q121+@q122+@q123+@q124+@q125+@q126+@q127+@q128+@q129+@q130+ @q131+@q132+@q133+@q134+@q135+@q136+@q137+@q138+@q139+@q140+ @q141+@q142+@q143+@q144+@q145+@q146+@q147+@q148+@q149+@q150+ @q151+@q152+@q153+@q154+@q155+@q156+@q157+@q158+@q159+@q160+ @q161+@q162+@q163+@q164+@q165+@q166+@q167+@q168+@q169+@q170+ @q171+@q172+@q173+@q174+@q175+@q176+@q177+@q178+@q179+@q180+ @q181+@q182+@q183+@q184+@q185+@q186+@q187+@q188+@q189+@q190+ @q191+@q192+@q193+@q194+@q195+@q196+@q197+@q198+@q199+@q200+ @q201+@q202+@q203+@q204+@q205+@q206+@q207+@q208+@q209+@q210+ @q211+@q212+@q213+@q214+@q215+@q216+@q217+@q218+@q219+@q220+ @q221+@q222+@q223+@q224+@q225+@q226+@q227+@q228+@q229+@q230+ @q231+@q232+@q233+@q234+@q235+@q236+@q237+@q238+@q239+@q240+ @q241+@q242+@q243+@q244+@q245+@q246+@q247+@q248+@q249+@q250) if @@error <> 0 begin goto Error end end else begin -- print out debug info select '@q1' = datalength(@q1)/2, '@q2' = datalength(@q2)/2, '@q3' = datalength(@q3)/2, '@q4' = datalength(@q4)/2, '@q5' = datalength(@q5)/2, '@q6' = datalength(@q6)/2, '@q7' = datalength(@q7)/2, '@q8' = datalength(@q8)/2, '@q9' = datalength(@q9)/2, '@q10' = datalength(@q10)/2, '@q11' = datalength(@q11)/2, '@q12' = datalength(@q12)/2, '@q13' = datalength(@q13)/2, '@q14' = datalength(@q14)/2, '@q15' = datalength(@q15)/2, '@q16' = datalength(@q16)/2, '@q17' = datalength(@q17)/2, '@q18' = datalength(@q18)/2, '@q19' = datalength(@q19)/2, '@q20' = datalength(@q20)/2, '@q21' = datalength(@q21)/2, '@q22' = datalength(@q22)/2, '@q23' = datalength(@q23)/2, '@q24' = datalength(@q24)/2, '@q25' = datalength(@q25)/2, '@q26' = datalength(@q26)/2, '@q27' = datalength(@q27)/2, '@q28' = datalength(@q28)/2, '@q29' = datalength(@q29)/2, '@q30' = datalength(@q30)/2, '@q31' = datalength(@q31)/2, '@q32' = datalength(@q32)/2, '@q33' = datalength(@q33)/2, '@q34' = datalength(@q34)/2, '@q35' = datalength(@q35)/2, '@q36' = datalength(@q36)/2, '@q37' = datalength(@q37)/2, '@q38' = datalength(@q38)/2, '@q39' = datalength(@q39)/2, '@q40' = datalength(@q40)/2, '@q41' = datalength(@q41)/2, '@q42' = datalength(@q42)/2, '@q43' = datalength(@q43)/2, '@q44' = datalength(@q44)/2, '@q45' = datalength(@q45)/2, '@q46' = datalength(@q46)/2, '@q47' = datalength(@q47)/2, '@q48' = datalength(@q48)/2, '@q49' = datalength(@q49)/2, '@q50' = datalength(@q50)/2, '@q51' = datalength(@q51)/2, '@q52' = datalength(@q52)/2, '@q53' = datalength(@q53)/2, '@q54' = datalength(@q54)/2, '@q55' = datalength(@q55)/2, '@q56' = datalength(@q56)/2, '@q57' = datalength(@q57)/2, '@q58' = datalength(@q58)/2, '@q59' = datalength(@q59)/2, '@q60' = datalength(@q60)/2, '@q61' = datalength(@q61)/2, '@q62' = datalength(@q62)/2, '@q63' = datalength(@q63)/2, '@q64' = datalength(@q64)/2, '@q65' = datalength(@q65)/2, '@q66' = datalength(@q66)/2, '@q67' = datalength(@q67)/2, '@q68' = datalength(@q68)/2, '@q69' = datalength(@q69)/2, '@q70' = datalength(@q70)/2, '@q71' = datalength(@q71)/2, '@q72' = datalength(@q72)/2, '@q73' = datalength(@q73)/2, '@q74' = datalength(@q74)/2, '@q75' = datalength(@q75)/2, '@q76' = datalength(@q76)/2, '@q77' = datalength(@q77)/2, '@q78' = datalength(@q78)/2, '@q79' = datalength(@q79)/2, '@q80' = datalength(@q80)/2, '@q81' = datalength(@q81)/2, '@q82' = datalength(@q82)/2, '@q83' = datalength(@q83)/2, '@q84' = datalength(@q84)/2, '@q85' = datalength(@q85)/2, '@q86' = datalength(@q86)/2, '@q87' = datalength(@q87)/2, '@q88' = datalength(@q88)/2, '@q89' = datalength(@q89)/2, '@q90' = datalength(@q90)/2, '@q91' = datalength(@q91)/2, '@q92' = datalength(@q92)/2, '@q93' = datalength(@q93)/2, '@q94' = datalength(@q94)/2, '@q95' = datalength(@q95)/2, '@q96' = datalength(@q96)/2, '@q97' = datalength(@q97)/2, '@q98' = datalength(@q98)/2, '@q99' = datalength(@q99)/2, '@q100' = datalength(@q100)/2, '@q101' = datalength(@q101)/2, '@q102' = datalength(@q102)/2, '@q103' = datalength(@q103)/2, '@q104' = datalength(@q104)/2, '@q105' = datalength(@q105)/2, '@q106' = datalength(@q106)/2, '@q107' = datalength(@q107)/2, '@q108' = datalength(@q108)/2, '@q109' = datalength(@q109)/2, '@q110' = datalength(@q110)/2, '@q111' = datalength(@q111)/2, '@q112' = datalength(@q112)/2, '@q113' = datalength(@q113)/2, '@q114' = datalength(@q114)/2, '@q115' = datalength(@q115)/2, '@q116' = datalength(@q116)/2, '@q117' = datalength(@q117)/2, '@q118' = datalength(@q118)/2, '@q119' = datalength(@q119)/2, '@q120' = datalength(@q120)/2, '@q121' = datalength(@q121)/2, '@q122' = datalength(@q122)/2, '@q123' = datalength(@q123)/2, '@q124' = datalength(@q124)/2, '@q125' = datalength(@q125)/2, '@q126' = datalength(@q126)/2, '@q127' = datalength(@q127)/2, '@q128' = datalength(@q128)/2, '@q129' = datalength(@q129)/2, '@q130' = datalength(@q130)/2, '@q131' = datalength(@q131)/2, '@q132' = datalength(@q132)/2, '@q133' = datalength(@q133)/2, '@q134' = datalength(@q134)/2, '@q135' = datalength(@q135)/2, '@q136' = datalength(@q136)/2, '@q137' = datalength(@q137)/2, '@q138' = datalength(@q138)/2, '@q139' = datalength(@q139)/2, '@q140' = datalength(@q140)/2, '@q141' = datalength(@q141)/2, '@q142' = datalength(@q142)/2, '@q143' = datalength(@q143)/2, '@q144' = datalength(@q144)/2, '@q145' = datalength(@q145)/2, '@q146' = datalength(@q146)/2, '@q147' = datalength(@q147)/2, '@q148' = datalength(@q148)/2, '@q149' = datalength(@q149)/2, '@q150' = datalength(@q150)/2, '@q151' = datalength(@q151)/2, '@q152' = datalength(@q152)/2, '@q153' = datalength(@q153)/2, '@q154' = datalength(@q154)/2, '@q155' = datalength(@q155)/2, '@q156' = datalength(@q156)/2, '@q157' = datalength(@q157)/2, '@q158' = datalength(@q158)/2, '@q159' = datalength(@q159)/2, '@q160' = datalength(@q160)/2, '@q161' = datalength(@q161)/2, '@q162' = datalength(@q162)/2, '@q163' = datalength(@q163)/2, '@q164' = datalength(@q164)/2, '@q165' = datalength(@q165)/2, '@q166' = datalength(@q166)/2, '@q167' = datalength(@q167)/2, '@q168' = datalength(@q168)/2, '@q169' = datalength(@q169)/2, '@q170' = datalength(@q170)/2, '@q171' = datalength(@q171)/2, '@q172' = datalength(@q172)/2, '@q173' = datalength(@q173)/2, '@q174' = datalength(@q174)/2, '@q175' = datalength(@q175)/2, '@q176' = datalength(@q176)/2, '@q177' = datalength(@q177)/2, '@q178' = datalength(@q178)/2, '@q179' = datalength(@q179)/2, '@q180' = datalength(@q180)/2, '@q181' = datalength(@q181)/2, '@q182' = datalength(@q182)/2, '@q183' = datalength(@q183)/2, '@q184' = datalength(@q184)/2, '@q185' = datalength(@q185)/2, '@q186' = datalength(@q186)/2, '@q187' = datalength(@q187)/2, '@q188' = datalength(@q188)/2, '@q189' = datalength(@q189)/2, '@q190' = datalength(@q190)/2, '@q191' = datalength(@q191)/2, '@q192' = datalength(@q192)/2, '@q193' = datalength(@q193)/2, '@q194' = datalength(@q194)/2, '@q195' = datalength(@q195)/2, '@q196' = datalength(@q196)/2, '@q197' = datalength(@q197)/2, '@q198' = datalength(@q198)/2, '@q199' = datalength(@q199)/2, '@q200' = datalength(@q200)/2, '@q201' = datalength(@q201)/2, '@q202' = datalength(@q202)/2, '@q203' = datalength(@q203)/2, '@q204' = datalength(@q204)/2, '@q205' = datalength(@q205)/2, '@q206' = datalength(@q206)/2, '@q207' = datalength(@q207)/2, '@q208' = datalength(@q208)/2, '@q209' = datalength(@q209)/2, '@q210' = datalength(@q210)/2, '@q211' = datalength(@q211)/2, '@q212' = datalength(@q212)/2, '@q213' = datalength(@q213)/2, '@q214' = datalength(@q214)/2, '@q215' = datalength(@q215)/2, '@q216' = datalength(@q216)/2, '@q217' = datalength(@q217)/2, '@q218' = datalength(@q218)/2, '@q219' = datalength(@q219)/2, '@q220' = datalength(@q220)/2, '@q221' = datalength(@q221)/2, '@q222' = datalength(@q222)/2, '@q223' = datalength(@q223)/2, '@q224' = datalength(@q224)/2, '@q225' = datalength(@q225)/2, '@q226' = datalength(@q226)/2, '@q227' = datalength(@q227)/2, '@q228' = datalength(@q228)/2, '@q229' = datalength(@q229)/2, '@q230' = datalength(@q230)/2, '@q231' = datalength(@q231)/2, '@q232' = datalength(@q232)/2, '@q233' = datalength(@q233)/2, '@q234' = datalength(@q234)/2, '@q235' = datalength(@q235)/2, '@q236' = datalength(@q236)/2, '@q237' = datalength(@q237)/2, '@q238' = datalength(@q238)/2, '@q239' = datalength(@q239)/2, '@q240' = datalength(@q240)/2, '@q241' = datalength(@q241)/2, '@q242' = datalength(@q242)/2, '@q243' = datalength(@q243)/2, '@q244' = datalength(@q244)/2, '@q245' = datalength(@q245)/2, '@q246' = datalength(@q246)/2, '@q247' = datalength(@q247)/2, '@q248' = datalength(@q248)/2, '@q249' = datalength(@q249)/2, '@q250' = datalength(@q250)/2 select @q1+@q2+@q3+@q4+@q5+@q6+@q7+@q8+@q9+@q10+ @q11+@q12+@q13+@q14+@q15+@q16+@q17+@q18+@q19+@q20+ @q21+@q22+@q23+@q24+@q25+@q26+@q27+@q28+@q29+@q30+ @q31+@q32+@q33+@q34+@q35+@q36+@q37+@q38+@q39+@q40+ @q41+@q42+@q43+@q44+@q45+@q46+@q47+@q48+@q49+@q50+ @q51+@q52+@q53+@q54+@q55+@q56+@q57+@q58+@q59+@q60+ @q61+@q62+@q63+@q64+@q65+@q66+@q67+@q68+@q69+@q70+ @q71+@q72+@q73+@q74+@q75+@q76+@q77+@q78+@q79+@q80+ @q81+@q82+@q83+@q84+@q85+@q86+@q87+@q88+@q89+@q90+ @q91+@q92+@q93+@q94+@q95+@q96+@q97+@q98+@q99+@q100+ @q101+@q102+@q103+@q104+@q105+@q106+@q107+@q108+@q109+@q110+ @q111+@q112+@q113+@q114+@q115+@q116+@q117+@q118+@q119+@q120+ @q121+@q122+@q123+@q124+@q125+@q126+@q127+@q128+@q129+@q130+ @q131+@q132+@q133+@q134+@q135+@q136+@q137+@q138+@q139+@q140+ @q141+@q142+@q143+@q144+@q145+@q146+@q147+@q148+@q149+@q150+ @q151+@q152+@q153+@q154+@q155+@q156+@q157+@q158+@q159+@q160+ @q161+@q162+@q163+@q164+@q165+@q166+@q167+@q168+@q169+@q170+ @q171+@q172+@q173+@q174+@q175+@q176+@q177+@q178+@q179+@q180+ @q181+@q182+@q183+@q184+@q185+@q186+@q187+@q188+@q189+@q190+ @q191+@q192+@q193+@q194+@q195+@q196+@q197+@q198+@q199+@q200+ @q201+@q202+@q203+@q204+@q205+@q206+@q207+@q208+@q209+@q210+ @q211+@q212+@q213+@q214+@q215+@q216+@q217+@q218+@q219+@q220+ @q221+@q222+@q223+@q224+@q225+@q226+@q227+@q228+@q229+@q230+ @q231+@q232+@q233+@q234+@q235+@q236+@q237+@q238+@q239+@q240+ @q241+@q242+@q243+@q244+@q245+@q246+@q247+@q248+@q249+@q250 end return 0 Error: return 1 end go exec sp_MS_marksystemobject N'dbo.sp_execresultset' go raiserror('Creating procedure sp_MSispulldistributionjobnamegenerated', 0,1) with nowait go -- -- Name: sp_MSispulldistributionjobnamegenerated -- -- Descriptions: This procedure checks whether a given job id corresponds to -- a pull distribution agent job with a name generated by replication. -- If so, a return value of zero will be returned, otherwise -- a value of one will be returned to the caller. -- -- Notes: 1) For this procedure to be effective, it must match the current -- pull distribution agent name generation algorithm. Note that the -- algorithm used for matching auto-generated job name is not -- exact. (See sp_addpullsubscription_agent replsys.sql) -- 2) This procedure is supposed to be executed at the subscriber -- database. The subscriber server name and subscriber database -- name for contructing the generated job name are obtained via -- the serverproperty('ServerName') and the db_name() functions. -- -- Parameters: @publisher sysname -- @publisher_db sysname -- @publication sysname (This can be null for shared agent) -- @job_id uniqueidentifier -- -- Returns: 0 - If the specified jobid corresponds to a snapshot job with -- a generated name. -- 1 - Otherwise -- -- Security: This is an internal system procedure. -- create procedure dbo.sp_MSispulldistributionjobnamegenerated ( @publisher sysname, @publisher_db sysname, @publication sysname, @job_id uniqueidentifier ) as begin set nocount on declare @generated_job_name nvarchar(4000) declare @generated_job_name_length int declare @job_name sysname select @job_name = null select @job_name = name from msdb.dbo.sysjobs_view where job_id = @job_id if @job_name is null begin goto MISMATCH end -- First of all, make sure that the job is indeed a distribution agent -- job (there should be a step with Distribution as the subsystem in the -- job) if not exists (select * from msdb.dbo.sysjobsteps where job_id = @job_id and upper(subsystem collate SQL_Latin1_General_CP1_CS_AS) = N'DISTRIBUTION') begin goto MISMATCH end -- Pull distribution agent names are always generated with a guid select @generated_job_name = left(@publisher, 21) + N'-' + left(@publisher_db, 21) + N'-' + left(@publication, 21) + N'-' + left(convert(nvarchar(4000),serverproperty('ServerName')), 21) + N'-' + left(db_name(), 21) + N'-' select @generated_job_name_length = len(@generated_job_name) -- Try matching the prefix of the job name if left(@job_name, @generated_job_name_length) = @generated_job_name begin -- Checks if the tail end of the job name matches a hexadecimal guid -- with embedded dashes if upper(right(@job_name, len(@job_name) - @generated_job_name_length) collate SQL_Latin1_General_CP1_CS_AS) like N'[0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F]-[0-9A-F][0-9A-F][0-9A-F][0-9A-F]-[0-9A-F][0-9A-F][0-9A-F][0-9A-F]-[0-9A-F][0-9A-F][0-9A-F][0-9A-F]-[0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F]' begin return 0 end else begin goto MISMATCH end end MISMATCH: if @job_name is not null begin raiserror(21695, -1, -1, @job_name) end return 1 end go exec sp_MS_marksystemobject N'dbo.sp_MSispulldistributionjobnamegenerated' raiserror('Creating procedure sp_MSispullmergejobnamegenerated', 0,1) with nowait go -- -- Name: sp_MSispullmergejobnamegenerated -- -- Descriptions: This procedure checks whether a given job id corresponds to -- a pull merge agent job with a name generated by replication. -- If so, a return value of zero will be returned, otherwise -- a value of one will be returned to the caller. -- -- Notes: 1) For this procedure to be effective, it must match the current -- pull merge agent name generation algorithm. Note that the -- algorithm used for matching auto-generated job name is not -- exact. (See sp_addmergepullsubscription_agent replsys.sql) -- 2) This procedure is supposed to be executed at the subscriber -- database. The subscriber server name and subscriber database -- name for contructing the generated job name are obtained via -- the serverproperty('ServerName') and the db_name() functions. -- -- Parameters: @publisher sysname -- @publisher_db sysname -- @publication sysname (This can be null for shared agent) -- @job_id uniqueidentifier -- -- Returns: 0 - If the specified jobid corresponds to a snapshot job with -- a generated name. -- 1 - Otherwise -- -- Security: This is an internal system procedure. -- create procedure dbo.sp_MSispullmergejobnamegenerated ( @publisher sysname, @publisher_db sysname, @publication sysname, @job_id uniqueidentifier ) as begin set nocount on declare @generated_job_name nvarchar(4000) declare @generated_job_name_length int declare @job_name sysname select @job_name = null select @job_name = name from msdb.dbo.sysjobs_view where job_id = @job_id if @job_name = null begin goto MISMATCH end -- First of all, make sure that the given job is indeed a merge agent -- job (There should be a step with Distribution as the subsystem in the -- job) if not exists (select * from msdb.dbo.sysjobsteps where job_id = @job_id and upper(subsystem collate SQL_Latin1_General_CP1_CS_AS) = N'MERGE') begin goto MISMATCH end -- Pull merge agent names are always generated with a - 0 extension select @generated_job_name = left(@publisher, 23) + N'-' + left(@publisher_db, 23) + N'-' + left(@publication, 23) + N'-' + left(convert(nvarchar(4000),serverproperty('ServerName')), 23) + N'-' + left(db_name(), 23) + N'- 0' if @job_name = @generated_job_name begin return 0 end MISMATCH: if @job_name is not null begin raiserror(21695, -1, -1, @job_name) end return 1 end go exec sp_MS_marksystemobject 'dbo.sp_MSispullmergejobnamegenerated' raiserror('Creating function fn_escapecmdshellsymbols', 0,1) with nowait go -- -- Name: fn_escapecmdshellsymbols -- -- Descriptions: This function returns an escaped version of a given string -- with carets ('^') added in front of all the special -- command shell symbols. In the W2K online help (Start-> -- Help->Index->Command Reference->Command Symbols...), the -- following symbols are listed as special command symbols: -- (N'%', N'<', N'>', N'|', N'&', N'(', N')', N'^', N'"') -- -- Parameter: @command_string nvarchar(4000) -- -- Example: select fn_escapecmdshellsymbols(N'The % quick < brown > dog | jumps & over ( the ) lazy ^ fox.') -- will return -- -- The ^% quick ^< brown ^> dog ^| jumps ^& over ^( the ^) lazy ^^ fox -- -- Security: This function is granted to public -- create function system_function_schema.fn_escapecmdshellsymbols( @command_string nvarchar(4000) ) returns nvarchar(4000) as begin declare @escaped_command_string nvarchar(4000), @curr_char nvarchar(1), @curr_char_index int select @escaped_command_string = N'', @curr_char = N'', @curr_char_index = 1 while @curr_char_index <= len(@command_string) begin select @curr_char = substring(@command_string, @curr_char_index, 1) if @curr_char in (N'%', N'<', N'>', N'|', N'&', N'(', N')', N'^', N'"') begin select @escaped_command_string = @escaped_command_string + N'^' end select @escaped_command_string = @escaped_command_string + @curr_char select @curr_char_index = @curr_char_index + 1 end return @escaped_command_string end go grant execute on system_function_schema.fn_escapecmdshellsymbols to public raiserror('Creating function fn_escapecmdshellsymbolsremovequotes', 0,1) with nowait go -- -- Name: fn_escapecmdshellsymbolsremovequotes -- -- Descriptions: The only difference between this function and -- fn_escapecmdshellsymbols is that "'s are removed from the -- resulting command line. -- -- Parameter: @command_string nvarchar(4000) -- -- Security: This function is granted to public -- create function system_function_schema.fn_escapecmdshellsymbolsremovequotes( @command_string nvarchar(4000) ) returns nvarchar(4000) as begin declare @escaped_command_string nvarchar(4000), @curr_char nvarchar(1), @curr_char_index int select @escaped_command_string = N'', @curr_char = N'', @curr_char_index = 1 while @curr_char_index <= len(@command_string) begin select @curr_char = substring(@command_string, @curr_char_index, 1) if @curr_char in (N'%', N'<', N'>', N'|', N'&', N'(', N')', N'^') begin select @escaped_command_string = @escaped_command_string + N'^' end if @curr_char <> '"' begin select @escaped_command_string = @escaped_command_string + @curr_char end select @curr_char_index = @curr_char_index + 1 end return @escaped_command_string end go grant execute on system_function_schema.fn_escapecmdshellsymbolsremovequotes to public print '' print 'Creating function fn_repltrimleadingzerosinhexstr' go -- -- Name: fn_repltrimleadingzerosinhexstr -- -- Description: This function is used for trimming the leading zeros -- of a 32-bit hexadecimal string. For example, -- select fn_repltrimleadingzerosinhexstr('0000abcd') would -- yield 'abcd'. A notable special case would be select -- fn_repltrimleadingzerosinhexstr('00000000') which yields -- the string '0' instead of ''. -- -- Parameter: @hexstr nchar(8) - @hexstr is expected to be a full -- hexadecimal representation of a 32-bit integer without the -- 0x prefix -- -- Notes: -- -- Returns: nvarchar(8) -- -- Security: Execute permission of this function is granted to public. -- create function system_function_schema.fn_repltrimleadingzerosinhexstr ( @hexstr nchar(8) ) returns nvarchar(8) as begin declare @trimmed_hexstr nvarchar(8), @i int select @i = 1 while @i < 8 begin if substring(@hexstr,@i,1) <> N'0' break; select @i = @i + 1 end select @trimmed_hexstr = substring(@hexstr,@i,8-@i+1) return @trimmed_hexstr end go grant execute on system_function_schema.fn_repltrimleadingzerosinhexstr to public print '' print 'Creating function fn_replinttobitstring' go -- -- Name: fn_replinttobitstring -- -- Description: This function returns the bit pattern in string format for -- the specified 32-bit integer. For example, select -- fn_replinttobitstring(0x80000001) would yield -- '10000000000000000000000000000001' -- -- Parameter: @number int -- -- Returns: char(32) -- -- Security: Execute permission of this function is granted to public. -- create function system_function_schema.fn_replinttobitstring( @number int ) returns char(32) as begin declare @bitstring nvarchar(32) if (@number & 0x80000000) <> 0 select @bitstring = '1' else select @bitstring = '0' if (@number & 0x40000000) <> 0 select @bitstring = @bitstring + '1' else select @bitstring = @bitstring + '0' if (@number & 0x20000000) <> 0 select @bitstring = @bitstring + '1' else select @bitstring = @bitstring + '0' if (@number & 0x10000000) <> 0 select @bitstring = @bitstring + '1' else select @bitstring = @bitstring + '0' if (@number & 0x08000000) <> 0 select @bitstring = @bitstring + '1' else select @bitstring = @bitstring + '0' if (@number & 0x04000000) <> 0 select @bitstring = @bitstring + '1' else select @bitstring = @bitstring + '0' if (@number & 0x02000000) <> 0 select @bitstring = @bitstring + '1' else select @bitstring = @bitstring + '0' if (@number & 0x01000000) <> 0 select @bitstring = @bitstring + '1' else select @bitstring = @bitstring + '0' if (@number & 0x00800000) <> 0 select @bitstring = @bitstring + '1' else select @bitstring = @bitstring + '0' if (@number & 0x00400000) <> 0 select @bitstring = @bitstring + '1' else select @bitstring = @bitstring + '0' if (@number & 0x00200000) <> 0 select @bitstring = @bitstring + '1' else select @bitstring = @bitstring + '0' if (@number & 0x00100000) <> 0 select @bitstring = @bitstring + '1' else select @bitstring = @bitstring + '0' if (@number & 0x00080000) <> 0 select @bitstring = @bitstring + '1' else select @bitstring = @bitstring + '0' if (@number & 0x00040000) <> 0 select @bitstring = @bitstring + '1' else select @bitstring = @bitstring + '0' if (@number & 0x00020000) <> 0 select @bitstring = @bitstring + '1' else select @bitstring = @bitstring + '0' if (@number & 0x00010000) <> 0 select @bitstring = @bitstring + '1' else select @bitstring = @bitstring + '0' if (@number & 0x00008000) <> 0 select @bitstring = @bitstring + '1' else select @bitstring = @bitstring + '0' if (@number & 0x00004000) <> 0 select @bitstring = @bitstring + '1' else select @bitstring = @bitstring + '0' if (@number & 0x00002000) <> 0 select @bitstring = @bitstring + '1' else select @bitstring = @bitstring + '0' if (@number & 0x00001000) <> 0 select @bitstring = @bitstring + '1' else select @bitstring = @bitstring + '0' if (@number & 0x00000800) <> 0 select @bitstring = @bitstring + '1' else select @bitstring = @bitstring + '0' if (@number & 0x00000400) <> 0 select @bitstring = @bitstring + '1' else select @bitstring = @bitstring + '0' if (@number & 0x00000200) <> 0 select @bitstring = @bitstring + '1' else select @bitstring = @bitstring + '0' if (@number & 0x00000100) <> 0 select @bitstring = @bitstring + '1' else select @bitstring = @bitstring + '0' if (@number & 0x00000080) <> 0 select @bitstring = @bitstring + '1' else select @bitstring = @bitstring + '0' if (@number & 0x00000040) <> 0 select @bitstring = @bitstring + '1' else select @bitstring = @bitstring + '0' if (@number & 0x00000020) <> 0 select @bitstring = @bitstring + '1' else select @bitstring = @bitstring + '0' if (@number & 0x00000010) <> 0 select @bitstring = @bitstring + '1' else select @bitstring = @bitstring + '0' if (@number & 0x00000008) <> 0 select @bitstring = @bitstring + '1' else select @bitstring = @bitstring + '0' if (@number & 0x00000004) <> 0 select @bitstring = @bitstring + '1' else select @bitstring = @bitstring + '0' if (@number & 0x00000002) <> 0 select @bitstring = @bitstring + '1' else select @bitstring = @bitstring + '0' if (@number & 0x00000001) <> 0 select @bitstring = @bitstring + '1' else select @bitstring = @bitstring + '0' return @bitstring end go grant execute on system_function_schema.fn_replinttobitstring to public print '' print 'Creating function fn_replbitstringtoint' go -- -- Name: fn_replbitstringtoint -- -- Description: This function returns the integer value of the specified -- 32-bit bit pattern in string format. -- -- Parameter: @bitstring char(32) -- -- Notes: -- -- Returns: int -- -- Security: Execute permission of this function is granted to public. -- create function system_function_schema.fn_replbitstringtoint( @bitstring char(32) ) returns int as begin declare @number int select @number = 0 if (substring(@bitstring,1,1) = '1') select @number = @number | 0x80000000 if (substring(@bitstring,2,1) = '1') select @number = @number | 0x40000000 if (substring(@bitstring,3,1) = '1') select @number = @number | 0x20000000 if (substring(@bitstring,4,1) = '1') select @number = @number | 0x10000000 if (substring(@bitstring,5,1) = '1') select @number = @number | 0x08000000 if (substring(@bitstring,6,1) = '1') select @number = @number | 0x04000000 if (substring(@bitstring,7,1) = '1') select @number = @number | 0x02000000 if (substring(@bitstring,8,1) = '1') select @number = @number | 0x01000000 if (substring(@bitstring,9,1) = '1') select @number = @number | 0x00800000 if (substring(@bitstring,10,1) = '1') select @number = @number | 0x00400000 if (substring(@bitstring,11,1) = '1') select @number = @number | 0x00200000 if (substring(@bitstring,12,1) = '1') select @number = @number | 0x00100000 if (substring(@bitstring,13,1) = '1') select @number = @number | 0x00080000 if (substring(@bitstring,14,1) = '1') select @number = @number | 0x00040000 if (substring(@bitstring,15,1) = '1') select @number = @number | 0x00020000 if (substring(@bitstring,16,1) = '1') select @number = @number | 0x00010000 if (substring(@bitstring,17,1) = '1') select @number = @number | 0x00008000 if (substring(@bitstring,18,1) = '1') select @number = @number | 0x00004000 if (substring(@bitstring,19,1) = '1') select @number = @number | 0x00002000 if (substring(@bitstring,20,1) = '1') select @number = @number | 0x00001000 if (substring(@bitstring,21,1) = '1') select @number = @number | 0x00000800 if (substring(@bitstring,22,1) = '1') select @number = @number | 0x00000400 if (substring(@bitstring,23,1) = '1') select @number = @number | 0x00000200 if (substring(@bitstring,24,1) = '1') select @number = @number | 0x00000100 if (substring(@bitstring,25,1) = '1') select @number = @number | 0x00000080 if (substring(@bitstring,26,1) = '1') select @number = @number | 0x00000040 if (substring(@bitstring,27,1) = '1') select @number = @number | 0x00000020 if (substring(@bitstring,28,1) = '1') select @number = @number | 0x00000010 if (substring(@bitstring,29,1) = '1') select @number = @number | 0x00000008 if (substring(@bitstring,30,1) = '1') select @number = @number | 0x00000004 if (substring(@bitstring,31,1) = '1') select @number = @number | 0x00000002 if (substring(@bitstring,32,1) = '1') select @number = @number | 0x00000001 return @number end go grant execute on system_function_schema.fn_replbitstringtoint to public print '' print 'Creating function fn_replrotr' go -- -- Name: fn_replrotr -- -- Description: This is just a T-SQL implementation of the C function -- _rotr(). -- -- Parameter: @number int -- @shift int -- -- Notes: The effective shift will the positive remainder of @shift -- divided by 32. _rotl() can be implemented by passing in -- a negative shift. -- -- Returns: int -- -- Security: Execute permission of this function is granted to public. -- create function system_function_schema.fn_replrotr( @number int, @shift int ) returns int as begin declare @bitstring char(32) select @shift = @shift % 32 if @shift < 0 select @shift = @shift + 32 if (@shift != 0) begin select @bitstring = fn_replinttobitstring(@number) select @bitstring = substring(@bitstring,32-@shift+1,@shift) + substring(@bitstring,1,32-@shift) select @number = fn_replbitstringtoint(@bitstring) end return @number end go grant execute on system_function_schema.fn_replrotr to public print '' print 'Creating function fn_replgenerateshorterfilenameprefix' go -- -- Name: fn_replgenerateshorterfilenameprefix -- -- Description: This function mimics the algorithm used by the snapshot -- agent to shorten any overly long component of a publication -- snapshot folder with "overly long" defined as more than -- 30 characters in length (as specified in the @truncated_len -- parameter of this function). -- -- Parameters: @prefix nvarchar(4000) -- @truncated_len int -- -- Notes: -- -- Returns: nvarchar(4000) -- -- Security: Execute permission on this function is granted to public. -- create function system_function_schema.fn_replgenerateshorterfilenameprefix( @prefix nvarchar(4000), @truncated_len int ) returns nvarchar(4000) as begin declare @HashValueIndex int, @HashValue int, @CurrentByte tinyint, @TruncatedString varbinary(8000), @i int, @TruncatedStringLen int, @prefix_to_be_returned nvarchar(4000) select @prefix_to_be_returned = @prefix if (len(@prefix) > @truncated_len) begin select @TruncatedString = convert(varbinary(8000),substring(@prefix,@truncated_len-8+1,len(@prefix)-@truncated_len+8)) select @TruncatedStringLen = len(@TruncatedString) select @HashValue = 0 select @i = 1 select @HashValueIndex = 0 while @i <= @TruncatedStringLen begin select @CurrentByte = convert(tinyint,substring(@TruncatedString,@i,1)) select @HashValue = @HashValue ^ fn_replrotr(@CurrentByte, -(8*@HashValueIndex)) select @HashValue = fn_replrotr(@HashValue, @HashValueIndex + 1) if @CurrentByte != 0 begin select @HashValueIndex = (@HashValueIndex + 1) % 4 end select @i = @i + 1 end select @prefix_to_be_returned = substring(@prefix,1,@truncated_len-8) select @prefix_to_be_returned = @prefix_to_be_returned + lower(fn_repltrimleadingzerosinhexstr(substring(master.dbo.fn_varbintohexstr(convert(varbinary(4),@HashValue)) collate database_default,3,8)) collate database_default) end return @prefix_to_be_returned end go grant execute on system_function_schema.fn_replgenerateshorterfilenameprefix to public print '' print 'Creating function fn_replcomposepublicationsnapshotfolder' go -- -- Name: fn_replcomposepublicationsnapshotfolder -- -- Description: This mimics the algorithm used by the snapshot agent for -- composing the name of a publication's snapshot folder. -- -- Parameters: @publisher sysname -- @publisher_db sysname -- @publication sysname -- -- Notes: -- -- Returns: nvarchar(255) -- -- Security: Execute permission of this function is granted to public. -- create function system_function_schema.fn_replcomposepublicationsnapshotfolder( @publisher sysname, @publisher_db sysname, @publication sysname ) returns nvarchar(255) as begin declare @snapshot_folder_name nvarchar(255) select @snapshot_folder_name = fn_replgenerateshorterfilenameprefix(@publisher,30) collate database_default + N'_' + fn_replgenerateshorterfilenameprefix(@publisher_db,30) collate database_default + N'_' + fn_replgenerateshorterfilenameprefix(@publication,30) collate database_default return @snapshot_folder_name end go grant execute on system_function_schema.fn_replcomposepublicationsnapshotfolder to public go -- -- Name: sp_MSdroparticleconstraints -- -- Description: This procedure is used by the Distribution Agent to purge all -- the existing check, PK, UK, and FK constraints on a table -- article at the Subscriber. -- -- Parameters: @destination_object sysname (mandatory) -- @destination_owner sysname (mandatory) -- -- Returns: 0 - succeeded -- 1 - failed -- -- Security: Procedural security check is done inside this procedure -- to make sure that the caller is either a member of the db_owner -- role of the subscriber database or a member of the sysadmin role -- of the subscription server -- print '' print 'Creating procedure sp_MSdroparticleconstraints' go create procedure dbo.sp_MSdroparticleconstraints ( @destination_object sysname, @destination_owner sysname ) as begin set nocount on declare @retcode int, @objid int, @constid int, @drop_command nvarchar(4000), @qualified_tablename nvarchar(540), @publish_bit int, @mergepublish_bit int select @retcode = 0, @objid = null, @constid = null, @drop_command = null, @qualified_tablename = null, @publish_bit = 1, @mergepublish_bit = 128 -- Security check exec @retcode = sp_MSreplcheck_subscribe if @retcode<>0 or @@error<>0 return 1 -- Get object id of the target table select @objid = id from sysobjects where name = @destination_object and (user_name(uid) = @destination_owner or @destination_owner is null or @destination_owner = N'') -- If the object is not at the subscriber, there isn't anything we -- can(or need to) do if @objid is null return 0 select @qualified_tablename = N'['+replace(@destination_object,N']',N']]')+N']' if @destination_owner is not null and @destination_owner<>N'' begin select @qualified_tablename = N'['+replace(@destination_owner,N']',N']]')+N'].'+@qualified_tablename end -- Skip constraint dropping for republished article if exists (select * from sysobjects where id = @objid and ((replinfo & @publish_bit <> 0) or (replinfo & @mergepublish_bit <> 0))) begin return 0 end declare hConst cursor local fast_forward for select constid from sysconstraints where id = @objid order by convert(int, objectproperty(constid,'IsForeignKey')) desc if @@error<>0 return 1 open hConst if @@error<>0 return 1 fetch hConst into @constid while (@@fetch_status<>-1) begin if objectproperty(@constid,N'IsUniqueCnst') = 1 or objectproperty(@constid,N'IsPrimaryKey') = 1 or objectproperty(@constid,N'IsCheckCnst') = 1 or objectproperty(@constid,N'IsForeignKey') = 1 begin select @drop_command = N'alter table '+@qualified_tablename+' drop constraint '+object_name(@constid) exec(@drop_command) if @@error <> 0 return 1 end fetch hConst into @constid end close hConst deallocate hConst return @retcode end go exec sp_MS_marksystemobject sp_MSdroparticleconstraints grant execute on sp_MSdroparticleconstraints to public -- -- Name: sp_MSacquireserverresourcefordynamicsnapshot -- -- Description: This is a light-weight wrapper of sp_MSacuireApplicationLock -- used by dynamic snapshot for governing the maximum number of -- concurrent dynamic snapshot sessions for a merge publication. -- -- Parameters: @publication sysname (mandatory) -- @max_concurrent_dynamic_snapshots int (mandatory) -- -- Security: Procedural security check is performed inside -- sp_MSacquireSlotLock to make sure that the caller is -- either sysadmin, db_owner, or replication agent. -- print '' print 'Creating procedure sp_MSacquireserverresourcefordynamicsnapshot' go create procedure dbo.sp_MSacquireserverresourcefordynamicsnapshot ( @publication sysname, @max_concurrent_dynamic_snapshots int ) as begin set nocount on declare @retcode int declare @pubid uniqueidentifier declare @process_name sysname select @retcode = 0 -- security check exec @retcode = dbo.sp_MSreplcheck_publish if @@ERROR <> 0 or @retcode <> 0 return 1 if object_id('sysmergepublications') is null begin raiserror(20026, 16, -1, @publication) return (1) end select @pubid = null select @pubid = pubid from sysmergepublications where name = @publication and publisher_db = db_name() and upper(publisher) = upper(@@servername) if @pubid is null begin raiserror(20026, 16, -1, @publication) return (1) end -- The following string construction will never overflow -- sysname select @process_name = N'ReplicationSnapshotAgent' + convert(nvarchar(40), @pubid) -- Acquire head of queue lock first exec @retcode = sp_MSacquireHeadofQueueLock @process_name = @process_name, @queue_timeout = 0, @no_result = 1 if @@error<>0 return (1) if @retcode<>0 goto Failure exec @retcode = sp_MSacquireSlotLock @process_name = @process_name, @concurrent_max = @max_concurrent_dynamic_snapshots if @@error<>0 return (1) Failure: return @retcode end go exec sp_MS_marksystemobject sp_MSacquireserverresourcefordynamicsnapshot go grant execute on sp_MSacquireserverresourcefordynamicsnapshot to public go -- -- Name: fn_replgetbinary8lodword -- -- Description: This function will get the lower dword of -- a given binary(8) value. For example: -- -- select fn_replgetbinary8lodword(0x0000000012345678) -- will return the integer -- 0x12345678 -- -- Parameter: @binary8_value binary(8) -- -- Returns: int -- -- Security: Execute permission of this function is granted -- to public -- print '' print 'Creating function fn_replgetbinary8lodword' go create function system_function_schema.fn_replgetbinary8lodword ( @binary8_value binary(8) ) returns int as begin declare @lodword int select @lodword = convert(int, substring(@binary8_value, 5, 4)) return @lodword end go grant execute on system_function_schema.fn_replgetbinary8lodword to public go -- -- Name: fn_replprepadbinary8 -- -- Description: This function is typically used by replication -- stored procedures to add padding 0s in front -- of a user-specified schema_option value. For -- example: -- -- select fn_replprepadbinary8(0x01) will return -- -- 0x0000000000000001 -- -- Parameter: @varbinary8_value varbinary(8) -- -- Returns: binary(8) -- -- Security: Execute permission of this function is granted -- to public -- print '' print 'Creating function fn_replprepadbinary8' go create function system_function_schema.fn_replprepadbinary8 ( @varbinary8_value varbinary(8) ) returns binary(8) as begin declare @padded_value binary(8) select @padded_value = substring(0x0000000000000000, 1, 8 - datalength(@varbinary8_value)) + @varbinary8_value return @padded_value end go grant execute on system_function_schema.fn_replprepadbinary8 to public go -- -- Name: fn_replmakestringliteral -- -- Description: This is a simple helper function for generating the unicode string -- literal representation of a given string. For example -- -- select fn_replmakestringliteral('string''literal') -- -- will return -- -- N'string''literal' -- -- Parameter: @string nvarchar(4000) -- -- Returns: nvarchar(4000) -- -- Security: Public access -- raiserror('Creating function fn_replmakestringliteral', 0,1) go create function system_function_schema.fn_replmakestringliteral ( @string nvarchar(4000) ) returns nvarchar(4000) as begin declare @string_literal nvarchar(4000) select @string_literal = N'N''' + replace(@string, '''', '''''') + N'''' return @string_literal end go grant execute on system_function_schema.fn_replmakestringliteral to public go -- -- Name: sp_MSgettranlastupdatedtime -- -- Description: This procedure retrieves the last updated time from the -- subscriber database for a transactional/snapshot -- subscription. -- -- Parameters: @publisher sysname (mandatory) -- @publisher_db sysname (mandatory) -- @publication sysname (mandatory) -- @subscription_type int (mandatory) -- Notes: This procedure should always be called internally by -- sp_MSgetlastupdatedtime -- -- Result: 'last updated time' nvarchar -- -- Returns 0 - succeeded -- 1 - failed -- -- Security: Sysadmin access only -- print 'Creating procedure sp_MSgettranlastupdatedtime' print '' go create procedure sp_MSgettranlastupdatedtime( @publisher sysname, @publisher_db sysname, @publication sysname, @subscription_type int ) as begin set nocount on declare @last_updated_time nvarchar(40) select @last_updated_time = null if object_id('MSreplication_subscriptions') is null begin select 'last updated time' = @last_updated_time raiserror(21384, 16, -1) return 1 end -- For subscriptions sharing an agent, -- the control may not be passing in the publication -- name. select @last_updated_time = convert(nvarchar(12), time, 112) + substring(convert(nvarchar(24), time, 121), 11,13) from MSreplication_subscriptions where upper(@publisher) = upper(publisher) and @publisher_db = publisher_db and (((@publication is null or @publication = N'') and independent_agent = 0) or (@publication = publication)) and @subscription_type = subscription_type select 'last updated time' = @last_updated_time if @last_updated_time is null begin raiserror(21384, 16, -1) return 1 end return 0 end go exec sp_MS_marksystemobject 'sp_MSgettranlastupdatedtime' -- -- Name: sp_MSgetmergelastupdatedtime -- -- Description: This procedure retrieves the last updated time from the -- subscriber database for a merge subscription. -- -- Parameters: @publisher sysname (mandatory) -- @publisher_db sysname (mandatory) -- @publication sysname (mandatory) -- @subscription_type int (mandatory) -- Notes: This procedure should always be called internally by -- sp_MSgetlastupdatedtime -- -- Result: 'last updated time' nvarchar -- -- Returns: 0 - succeeded -- 1 - failed -- -- Security: Sysadmin access only -- print 'Creating procedure sp_MSgetmergelastupdatedtime' print '' go create procedure sp_MSgetmergelastupdatedtime( @publisher sysname, @publisher_db sysname, @publication sysname, @subscription_type int ) as begin set nocount on declare @last_updated_time nvarchar(40) declare @last_updated_datetime datetime select @last_updated_datetime = null select @last_updated_time = null if object_id('sysmergesubscriptions') is null or object_id('sysmergepublications') is null begin select 'last updated time' = @last_updated_time raiserror(21384, 16, -1) return 1 end select @last_updated_datetime = last_sync_date from sysmergesubscriptions sms inner join sysmergepublications smp on sms.pubid = smp.pubid where upper(@@servername) = upper(sms.subscriber_server) and sms.db_name = db_name() and sms.subscription_type = @subscription_type and upper(smp.publisher) = upper(publisher) and smp.publisher_db = @publisher_db and smp.name = @publication if @last_updated_datetime is not null begin select @last_updated_time = convert(nvarchar(12), @last_updated_datetime, 112) + substring(convert(nvarchar(24), @last_updated_datetime, 121), 11,13) end select 'last updated time' = @last_updated_time if @last_updated_time is null begin raiserror(21384, 16, -1) return 1 end return 0 end go exec sp_MS_marksystemobject 'sp_MSgetmergelastupdatedtime' -- -- Name: sp_MSgetlastupdatedtime -- -- Description: This procedure is used internally by the ActiveX controls -- to retrieve the last updated time of the specified -- subscription. -- -- Parameters: @publisher sysname (mandatory) -- @publisher_db sysname (mandatory) -- @publication sysname (mandatory) -- @subscription_type int (mandatory) -- @publication_type int (mandatory) (1 - transactional/snapshot -- 2 - merge) -- Returns: 0 - succeeded -- 1 - failed -- -- Result: 'last updated time' nvarchar -- -- Security: Execute permission of this stored procedure is granted to public -- but security check is performed inside the procedure to make -- sure that only dbo of the subscriber database and server admin -- can retrieve the last updated time successfully. -- print 'Creating procedure sp_MSgetlastupdatedtime' print '' go create procedure sp_MSgetlastupdatedtime( @publisher sysname, @publisher_db sysname, @publication sysname, @subscription_type int, @publication_type int -- 1 - transactional/snapshot, 2 - merge ) as begin set nocount on declare @retcode int select @retcode = 0 -- Security check exec @retcode = sp_MSreplcheck_subscribe if @retcode<>0 or @@error<>0 return 1 if @publication_type in (0,1) begin exec @retcode = sp_MSgettranlastupdatedtime @publisher, @publisher_db, @publication, @subscription_type end else begin exec @retcode = sp_MSgetmergelastupdatedtime @publisher, @publisher_db, @publication, @subscription_type end return @retcode end go exec sp_MS_marksystemobject 'sp_MSgetlastupdatedtime' -- -- Name: fn_repladjustcolumnmap -- -- Description: This function adjusts the bitmap for subscriber/destination tables -- that have been altered and the relative column order do not match the actual -- column id. The column_updated() bitmap for such tables need to be adjusted to -- reflect relative column order before sending them to publisher -- -- Parameters: -- @objid int - destination table object id -- ,@total_col int - total number of columns in the table -- ,@inmap varbinary(4000) input bitmap that is based on actual column id -- -- Returns: varbinary(4000) output column that is based on relative column order -- -- Security: Execute permission of this function is granted to public -- raiserror('Creating function fn_repladjustcolumnmap', 0,1) go create function system_function_schema.fn_repladjustcolumnmap ( @objid int ,@total_col int ,@inmap varbinary(4000) ) returns varbinary(4000) as begin declare @colmap table (relativeorder int identity(1,1), colid int) declare @outmap varbinary(4000) ,@relpos int ,@colid int ,@bytepos int ,@bitpos int ,@num_bytes int -- -- initialize -- select @outmap = 0 insert into @colmap (colid) select colid from syscolumns where id = @objid order by colid if (@@error != 0) begin return cast(NULL as varbinary(4000)) end -- -- for each column in the column map -- declare #colmap_cursor cursor local fast_forward for select relativeorder, colid from @colmap order by relativeorder for read only open #colmap_cursor fetch #colmap_cursor into @relpos, @colid while (@@fetch_status = 0) begin -- -- select the absolute column position -- select @bytepos = 1 + ((@colid-1) / 8) ,@bitpos = power(2, (@colid-1) % 8 ) if (substring(@inmap, @bytepos, 1) & @bitpos = @bitpos) begin -- -- set the relative position for this column in the output -- select @bytepos = 1 + ((@relpos-1) / 8) ,@bitpos = power(2, (@relpos-1) % 8 ) ,@num_bytes = @total_col / 8 + 1 select @outmap = substring(@outmap, 1, (@bytepos - 1)) + (convert(binary(1), substring(@outmap, @bytepos, 1) | convert(tinyint,@bitpos))) + substring(@outmap, (@bytepos + 1), (@num_bytes - @bytepos)) end -- fetch next column mapping fetch #colmap_cursor into @relpos, @colid end close #colmap_cursor deallocate #colmap_cursor return @outmap end go grant execute on system_function_schema.fn_repladjustcolumnmap to public -- -- Name: fn_replquotename -- -- Description: This is simply a more complete implementation of quote_name() -- that can handle longer strings. Note that this function is -- hard-coded to do square-bracket quoting only. -- -- Parameter: @string nvarchar(1998) -- -- Returns: nvarchar(4000) -- -- Security: Execute permission of this function is granted to public -- print 'Creating function fn_replquotename' print '' go create function system_function_schema.fn_replquotename( @string nvarchar(1998) ) returns nvarchar(4000) begin declare @resulting_string nvarchar(4000) declare @string_len int declare @char nchar(1) declare @index int select @resulting_string = null if @string is not null begin select @string_len = len(@string) select @index = 1 select @resulting_string = N'[' while @index <= @string_len begin select @char = substring(@string, @index, 1) select @resulting_string = @resulting_string + @char if @char = N']' begin select @resulting_string = @resulting_string + N']' end select @index = @index + 1 end select @resulting_string = @resulting_string + N']' end return @resulting_string end go -- -- Name: fn_chariswhitespace -- -- Description: This is a very simple function that checks whether a given -- character is a white-space. -- -- Parameters: @char nchar(1) -- -- Notes: -- -- Returns: bit -- 0 - The given character is not a white-space -- 1 - The given character is a white-space -- -- Security: Execute permission of this function is granted to public -- print 'Creating function fn_chariswhitespace' print '' go create function system_function_schema.fn_chariswhitespace( @char nchar(1) ) returns bit begin declare @result bit if @char in (N' ', nchar(9), nchar(10), nchar(13), N'') begin select @result = 1 end else begin select @result = 0 end return @result end go -- -- Name: fn_generateparameterpattern -- -- Description: Given the name of a parameter (excluding the leading / or -), -- this function will return the pattern for matching the -- parameter in a case-insensitive manner. For example -- -- select fn_generateparameterpattern(N'Ouptut') -- -- will return -- -- %[-/][Oo][Uu][Tt][Pp][Uu][Tt]% -- -- Parameters: @parameter nvarchar(200) -- -- Notes: The leading / or - should be omitted from @parameter -- -- Returns: nvarchar(806) -- -- Security: Execute permission of this function is granted to public -- print 'Creating function fn_generateparameterpattern' print '' go create function system_function_schema.fn_generateparameterpattern( @parameter nvarchar(200) ) returns nvarchar(806) begin declare @pattern nvarchar(806) declare @parameter_length int declare @i int declare @c nvarchar(1) select @pattern = N'%[-/]' select @i = 1 select @parameter_length = len(@parameter) while @i <= @parameter_length begin select @c = substring(@parameter, @i, 1) select @pattern = @pattern + N'[' + upper(@c collate SQL_Latin1_General_CP1_CS_AS) + lower(@c collate SQL_Latin1_General_CP1_CS_AS) + N']' select @i = @i + 1 end select @pattern = @pattern + '%' return @pattern end go -- -- Name: fn_skipparameterargument -- -- Description: This function basically removes the first non-parameter -- token from the given command. It is designed to handle -- square-bracket quoted or double-quoted parameter arguments. -- Note that all white-spaces trailing the removed argument will -- also be removed in the returned command. -- -- Parameters: @command nvarchar(3200) -- -- Returns: nvarchar(3200) -- -- Security: Execute permission of this function is granted to public -- print 'Creating function fn_skipparameterargument' print '' go create function system_function_schema.fn_skipparameterargument( @command nvarchar(3200) ) returns nvarchar(3200) begin declare @state int declare @i int declare @char nvarchar(1) declare @command_length int declare @state_start int declare @state_in_dquote_argument int declare @state_seen_matching_dquote int declare @state_in_square_bracket_argument int declare @state_seen_matching_bracket int declare @state_reached_end_of_argument int declare @state_in_unquoted_argument int declare @state_exit int -- Initializations select @state_start = 0 select @state_in_dquote_argument = 1 select @state_seen_matching_dquote = 2 select @state_in_square_bracket_argument = 3 select @state_seen_matching_bracket = 4 select @state_reached_end_of_argument = 5 select @state_in_unquoted_argument = 6 select @state_exit = 7 select @i = 1 select @state = @state_start select @command_length = len(@command) while @i <= @command_length begin select @char = substring(@command,@i,1) select @state = case @state when @state_start then case when fn_chariswhitespace(@char) = 1 then @state_start when @char in (N'-',N'/') then @state_exit when @char in (N'[') then @state_in_square_bracket_argument when @char in (N'"') then @state_in_dquote_argument else @state_in_unquoted_argument end when @state_in_dquote_argument then case when @char in (N'"') then @state_seen_matching_dquote else @state_in_dquote_argument end when @state_seen_matching_dquote then case when @char in (N'"') then @state_in_dquote_argument when fn_chariswhitespace(@char) = 1 then @state_reached_end_of_argument else @state_exit end when @state_in_square_bracket_argument then case when @char in (N']') then @state_seen_matching_bracket else @state_in_square_bracket_argument end when @state_seen_matching_bracket then case when @char in (N']') then @state_in_square_bracket_argument when fn_chariswhitespace(@char) = 1 then @state_reached_end_of_argument else @state_exit end when @state_reached_end_of_argument then case when fn_chariswhitespace(@char) = 1 then @state_reached_end_of_argument else @state_exit end when @state_in_unquoted_argument then case when fn_chariswhitespace(@char) = 1 then @state_reached_end_of_argument else @state_in_unquoted_argument end else @state end if @state = @state_exit begin goto done end select @i = @i + 1 end -- while done: select @command = substring(@command, @i, @command_length - @i + 1) return @command end go -- -- Name: fn_removeparameterwithargument -- -- Description: This function removes all instances of a parameter and their -- arguments from a given command line. -- -- Notes: @parameter must be specified without the leading / or - -- -- Parameters: @command nvarchar(3200) -- @parameter nvarchar(200) -- -- Returns: @nvarchar(3200) -- -- Security: Execute permission of this function is granted to public -- print 'Creating function fn_reomveparameterwithargument' print '' go create function system_function_schema.fn_removeparameterwithargument( @command nvarchar(3200), @parameter nvarchar(200) ) returns nvarchar(3200) begin declare @pattern nvarchar(806) declare @resulting_command nvarchar(3200) declare @command_length int declare @pattern_start int declare @first_iteration bit declare @parameter_length int select @first_iteration = 1 select @pattern = fn_generateparameterpattern(@parameter) select @parameter_length = len(@parameter) + 1 -- leading - or / select @resulting_command = N'' select @pattern_start = patindex(@pattern,@command) while @pattern_start <> 0 and @pattern_start is not NULL begin select @command_length = len(@command) -- Check if the pattern found is properly delimited in the command. -- If so, try to skip over the next token. if (@pattern_start = 1 and @first_iteration = 1 or (@pattern_start > 1 and fn_chariswhitespace(substring(@command, @pattern_start - 1, 1)) = 1)) and (fn_chariswhitespace(substring(@command, @pattern_start + @parameter_length, 1)) = 1) begin -- Add everything before the parameter to the resulting command select @resulting_command = @resulting_command + rtrim(substring(@command, 1, @pattern_start - 1)) -- Eat the parameter select @command = substring(@command, @pattern_start + @parameter_length, @command_length - @pattern_start - @parameter_length + 1) -- Skip over the argument of the parameter select @command = fn_skipparameterargument(@command) if @resulting_command <> N'' begin select @resulting_command = @resulting_command + N' ' end end else begin -- Not a properly delimited parameter so transfer the -- matching substring to the resulting command and -- eat the substring in the process select @resulting_command = @resulting_command + substring(@command, 1, @pattern_start + @parameter_length - 1) select @command = substring(@command, @pattern_start + @parameter_length, @command_length - @pattern_start - @parameter_length + 1) end select @first_iteration = 0 select @pattern_start = patindex(@pattern, @command) end select @resulting_command = @resulting_command + @command return @resulting_command end go -- -- Name: fn_updateparameterwithargument -- -- Description: This function updates the argument value of the specified -- parameter in the given command line. If there are multiple -- instances of the specified parameter in the command line, -- only the first instance will be updated and all subsequent -- instances will be removed. If the command line does not -- contain the specified parameter in the first place, this -- function will append the specified parameter and argument -- to the command line. -- -- Notes: Any quoting that is required for the argument should be done -- before calling this function. -- -- Parameters: @command nvarchar(3200) -- @parameter nvarchar(200) -- @argument nvarchar(1000) -- -- Returns: nvarchar(3200) -- -- Security: Execute permission of this function is granted to public -- print 'Creating function fn_updateparameterwithargument' print '' go create function system_function_schema.fn_updateparameterwithargument( @command nvarchar(3200), @parameter nvarchar(200), @argument nvarchar(1000) ) returns nvarchar(3200) begin declare @pattern nvarchar(806) declare @resulting_command nvarchar(3200) declare @command_length int declare @pattern_start int declare @first_iteration bit declare @parameter_length int declare @found_parameter bit select @first_iteration = 1 select @found_parameter = 0 select @pattern = fn_generateparameterpattern(@parameter) select @parameter_length = len(@parameter) + 1 -- leading - or / select @resulting_command = N'' select @pattern_start = patindex(@pattern,@command) if @argument is null begin select @argument = N'' end while @pattern_start <> 0 and @pattern_start is not null begin select @command_length = len(@command) -- Check if the pattern found is properly delimited in the command, -- If so, try to change the argument of the parameter with the given -- value. if (@pattern_start = 1 and @first_iteration = 1 or (@pattern_start > 1 and fn_chariswhitespace(substring(@command, @pattern_start - 1, 1)) = 1)) and (fn_chariswhitespace(substring(@command, @pattern_start + @parameter_length, 1)) = 1) begin -- Add everything before the parameter to the resulting command select @resulting_command = @resulting_command + rtrim(substring(@command, 1, @pattern_start - 1)) -- Add back the parameter with the specified argument if @resulting_command <> '' begin select @resulting_command = @resulting_command + N' ' end select @resulting_command = @resulting_command + N'-' + @parameter + N' ' + rtrim(ltrim(@argument)) + ' ' -- Remove the leading part of the command up to the begining of the -- matching pattern select @command = substring(@command, @pattern_start, @command_length - @pattern_start + 1) -- Remove all traces of the specified parameter from the remaining -- command line select @command = fn_removeparameterwithargument(@command, @parameter) select @found_parameter = 1 end else begin -- Not a properly delimited parameter so transfer the -- matching substring to the resulting command and -- eat the substring in the process select @resulting_command = @resulting_command + substring(@command, 1, @pattern_start + @parameter_length - 1) select @command = substring(@command, @pattern_start + @parameter_length, @command_length - @pattern_start - @parameter_length + 1) end select @first_iteration = 0 select @pattern_start = patindex(@pattern, @command) end select @resulting_command = @resulting_command + @command if @found_parameter = 0 begin select @resulting_command = rtrim(@resulting_command) + N' ' + N'-' + @parameter + N' ' + rtrim(ltrim(@argument)) end return @resulting_command end go -- -- Name: sp_MSreplcheckoffloadserver -- -- Description: A simple procedure for checking whether a specified -- offload server name contains invalid characters. -- -- Parameter: @offloadserver sysname (mandatory) -- -- Security: Admin only -- -- Returns: 0 - The specified offload server name doesn't contain invalid -- characters -- 1 - The specified offload server name contains invalid characters -- print '' print 'Creating procedure sp_MSreplcheckoffloadserver' go create procedure sp_MSreplcheckoffloadserver ( @offloadserver sysname ) as begin -- @offload_server being null is ok -- look for '\' if 0 < charindex('\', @offloadserver) begin raiserror(21368,-1,-1,N'\') return 1 end return 0 end go exec sp_MS_marksystemobject sp_MSreplcheckoffloadserver go -- -- Name: fn_MSrepl_get_unique_name -- -- Description: Use the prefixes passed in to generate a unique name based on a new GUID -- which is less than 100 characters (100 is task name limit) as -- 'prefix1-prefix2-prefix3-prefix4-hex_of_guid' -- All prefixes are optional. -- -- Security: To public -- raiserror('Creating function fn_repluniquename', 0,1) go create function system_function_schema.fn_repluniquename ( -- cannot use newid() in a UDF @guid uniqueidentifier, @prefix1 sysname = NULL, @prefix2 sysname = NULL, @prefix3 sysname = NULL, @prefix4 sysname = NULL ) returns nvarchar(100) as begin declare @name nvarchar(100) select @name = N'' -- Max len is (16 + 1) * 4 + 32 = 100 if @prefix1 is not null select @name = @name + CONVERT(nvarchar(16),@prefix1) + N'-' if @prefix2 is not null select @name = @name + CONVERT(nvarchar(16),@prefix2) + N'-' if @prefix3 is not null select @name = @name + CONVERT(nvarchar(16),@prefix3) + N'-' if @prefix4 is not null select @name = @name + CONVERT(nvarchar(16),@prefix4) + N'-' select @name = @name + replace(convert(nvarchar(36), @guid), N'-',N'') return @name end go print '' print 'Creating procedure sp_MSget_file_existence' go create procedure sp_MSget_file_existence ( @filename nvarchar(260), @exists bit = 0 output ) AS SET NOCOUNT ON DECLARE @command nvarchar(512) DECLARE @retcode int declare @echo_text nvarchar(20) select @echo_text = 'file_exists' /* ** The return code from xp_cmdshell is not a reliable way to check whether the file exists or ** not. It is always 0 on Win95 as long as xp_cmdshell succeeds. */ select @command = N'if exist "' + fn_escapecmdshellsymbolsremovequotes(@filename) collate database_default + N'" echo ' + @echo_text create table #text_ret(cmdoutput nvarchar(20) collate database_default null) insert into #text_ret exec @retcode = master..xp_cmdshell @command if @@error <> 0 or @retcode <> 0 return 1 if exists (select * from #text_ret where ltrim(rtrim(cmdoutput)) = @echo_text) select @exists = 1 else select @exists = 0 drop table #text_ret go EXEC dbo.sp_MS_marksystemobject sp_MSget_file_existence GO raiserror('Creating procedure sp_MSrepl_isdbowner', 0,1) go CREATE PROCEDURE sp_MSrepl_isdbowner @dbname nvarchar(255) AS BEGIN SET NOCOUNT ON DECLARE @retcode int DECLARE @cmd nvarchar(255) DECLARE @isdbowner int SELECT @retcode = has_dbaccess(@dbname) IF (@retcode IS NULL) OR (@retcode = 0) BEGIN /* ** Either no access or database not found ** No need to go further */ RETURN 0 END SELECT @cmd = 'USE ' + quotename(@dbname) + ' SELECT @isdbowner = is_member(''db_owner'')' EXEC sp_executesql @cmd, N'@isdbowner int output', @isdbowner output RETURN isnull(@isdbowner, 0) END GO raiserror('Creating procedure sp_resyncmergesubscription', 0,1) go CREATE PROCEDURE sp_resyncmergesubscription @publisher sysname = NULL, @publisher_db sysname = NULL, @publication sysname, @subscriber sysname = NULL, @subscriber_db sysname = NULL, @resync_type int, --0:force convergence, 1: since last successful validation, 2:since a given date @resync_date_str nvarchar(30) = NULL AS declare @retcode int declare @subid uniqueidentifier declare @pubid uniqueidentifier declare @subscriber_srvid int declare @resync_gen int declare @resync_date datetime /* ** Security Check */ EXEC @retcode = dbo.sp_MSreplcheck_publish IF @@ERROR <> 0 or @retcode <> 0 return (1) if isdate(@resync_date_str)=0 and @resync_type=2 begin raiserror(21370, 16, -1, @resync_date_str) return (1) end if @resync_date_str is not NULL select @resync_date=convert(datetime, @resync_date_str) else select @resync_date = NULl /* ** parameter checking for null/not-null; including validity of @resync_type and @resync_date */ if ((@publisher is NULL and @subscriber is NULL) or (@publisher is not NULL and @subscriber is not NULL) or (@publisher is NULL and @publisher_db is not NULL) or (@subscriber is NULL and @subscriber_db is not NULL) or (@publisher is not NULL and @publisher_db is NULL) or (@subscriber is not NULL and @subscriber_db is NULL)) begin raiserror(21294, 16, -1) return (1) end if @resync_type<0 or @resync_type>2 begin raiserror(21296, 16, -1) return (1) end if @publisher is NULL select @publisher=@@SERVERNAME if @publisher_db is NULL select @publisher_db=db_name() if @subscriber is NULL select @subscriber=@@SERVERNAME if @subscriber_db is NULL select @subscriber_db=db_name() select @pubid = pubid from sysmergepublications where name=@publication and lower(publisher)=lower(@publisher) and publisher_db=@publisher_db if (@pubid is null) begin RAISERROR (20026, 16, -1, @publication) return (1) end select @subscriber_srvid=srvid from master..sysservers where LOWER(srvname)=LOWER(@subscriber) collate database_default select @subid=subid from sysmergesubscriptions where pubid=@pubid and srvid=@subscriber_srvid and db_name=@subscriber_db if @resync_type > 0 --since a given date or last validation begin if @resync_type = 1 -- last validation time; make sure resync_date is not NULL in this case; begin select @resync_date=last_validated from sysmergesubscriptions where subid=@subid -- invalid case - there is no prior validation, this call is a non-op. if @resync_date is NULL begin raiserror(21370, 16, -1) return (1) end end declare @guidnull uniqueidentifier set @guidnull= '00000000-0000-0000-0000-000000000000' exec sp_MSlocalizeinterruptedgenerations select @resync_gen=NULL select top 1 @resync_gen=generation from MSmerge_genhistory where coldate > @resync_date and art_nick in (select nickname from sysmergearticles where pubid=@pubid) and guidlocal <> @guidnull order by coldate ASC -- this is valid case, meaning there is no need to do any resynchronization if @resync_gen is NULL begin return (0) end end else if @resync_type=0 select @resync_gen=0 -- force convergence case update sysmergesubscriptions set resync_gen=@resync_gen where subid=@subid if @@ERROR<>0 begin raiserror(21298, 16, -1) return (1) end Go EXEC dbo.sp_MS_marksystemobject sp_resyncmergesubscription GO grant exec on sp_resyncmergesubscription to public go raiserror('Creating procedure sp_MSget_qualified_name', 0,1) GO CREATE PROCEDURE sp_MSget_qualified_name ( @object_id int, @qualified_name nvarchar(512) output )AS if object_name(@object_id) is not null select @qualified_name = quotename(user_name(OBJECTPROPERTY(@object_id,'OwnerId'))) collate database_default + N'.' + quotename(object_name(@object_id)) collate database_default else select @qualified_name = NULL GO exec dbo.sp_MS_marksystemobject sp_MSget_qualified_name go raiserror('Creating procedure sp_MSdrop_object', 0,1) GO CREATE PROCEDURE sp_MSdrop_object ( @object_id int = NULL, @object_name sysname = NULL, @object_owner sysname = NULL ) AS SET NOCOUNT ON declare @cmd nvarchar(1000) if @object_name is not null begin declare @owner_id int if @object_owner is null select @owner_id = user_id() else select @owner_id = user_id(@object_owner) select @object_id = id from sysobjects where name = @object_name and uid = @owner_id end if @object_id is not null begin exec dbo.sp_MSget_qualified_name @object_id, @cmd output if objectproperty(@object_id, 'IsTable') = 1 select @cmd = 'drop table ' + @cmd else if objectproperty(@object_id, 'IsProcedure') = 1 select @cmd = 'drop procedure ' + @cmd else if objectproperty(@object_id, 'IsTrigger') = 1 select @cmd = 'drop trigger ' + @cmd else if objectproperty(@object_id, 'IsView') = 1 select @cmd = 'drop view ' + @cmd end exec (@cmd) if @@error <> 0 return(1) GO print '' print 'Creating procedure sp_isarticlecolbitset' go create procedure sp_isarticlecolbitset @colid int, @colbitmap binary(32) as declare @word tinyint declare @mval int declare @mask smallint select @word = convert(tinyint, 16 - floor((@colid-1)/16)) select @mval = power(2, (@colid-1) % 16 ) select @mask = convert( smallint, convert( binary(2), substring( convert( nchar(2), convert( binary(4), @mval ) ), 2, 1 ) ) ) if convert( binary(2), substring( convert( nchar(16),@colbitmap), @word, 1 ) ) & @mask = @mask begin return 1 end else begin return 0 end go EXEC dbo.sp_MS_marksystemobject sp_isarticlecolbitset GO print '' print 'Creating procedure sp_getarticlepkcolbitmap' go create procedure sp_getarticlepkcolbitmap @tabid int, @colbitmap binary(32) output as declare @pkindid int declare @indkey int declare @colid int declare @word tinyint declare @mval int declare @mask binary(2) declare @wordval binary(2) declare @objname nvarchar(265) select @colbitmap = 0x00 if exists( select * from sysobjects where id = @tabid and xtype = 'V' ) begin select @pkindid = 1 end else begin select @pkindid = indid from sysindexes where id = @tabid and status & 2048 <> 0 end select @indkey = 1 select @objname = QUOTENAME(user_name(OBJECTPROPERTY(@tabid, 'OwnerId'))) collate database_default + N'.' collate database_default + QUOTENAME(object_name( @tabid )) collate database_default while @indkey <= 16 and index_col( @objname, @pkindid, @indkey ) is not null begin select @colid = colid from syscolumns where id = @tabid and name = index_col( @objname, @pkindid, @indkey ) select @word = convert(tinyint, 16 - floor((@colid-1)/16)) select @mval = power(2, (@colid-1) % 16 ) select @mask = convert( binary(2), substring( convert( nchar(2), convert( binary(4), @mval ) ), 2, 1 ) ) select @wordval = convert( binary(2), substring( convert( nchar(16), @colbitmap ), @word, 1 ) ) select @wordval = convert( binary(2), convert( smallint, @wordval) | convert( smallint, @mask) ) select @colbitmap = convert(binary(32), STUFF( convert(nchar(16),@colbitmap), @word, 1, convert( nchar(1),@wordval))) select @indkey = @indkey + 1 end go EXEC dbo.sp_MS_marksystemobject sp_getarticlepkcolbitmap GO raiserror('Creating procedure sp_MSsubst_filter_name', 0,1) GO create procedure sp_MSsubst_filter_name @srch_string nvarchar(500), @rplc_string nvarchar(500), @filter_clause nvarchar(4000) output as declare @expansion int -- BYTES data will be expanded/contracted by declare @subst_offset int -- CHARACTER OFFSET at which to perform string operations select @expansion = datalength(@rplc_string) - datalength(@srch_string) select @subst_offset = 0 -- Note! procedure is case insensitive select @subst_offset = charindex( upper(@srch_string), upper(@filter_clause), @subst_offset ) while( @subst_offset <> 0 ) begin if datalength( @filter_clause ) + @expansion > 8000 begin -- buffer overflow, return error return 1 end else begin select @filter_clause = stuff( @filter_clause, @subst_offset, datalength( @srch_string ) / 2, @rplc_string ) select @subst_offset = @subst_offset + @expansion / 2 end select @subst_offset = charindex( upper(@srch_string), upper(@filter_clause), @subst_offset ) end return 0 go raiserror('Creating procedure sp_MSsubst_filter_names', 0,1) GO create procedure sp_MSsubst_filter_names @owner sysname, @table sysname, @filter_clause nvarchar(4000) output as declare @retcode int declare @rplc_string nvarchar( 513 ) if @filter_clause is null or @table is null begin -- error, @filter_clause cannot be null return 1 end if @owner is not null begin select @rplc_string = QUOTENAME(@owner) + N'.' end else begin select @rplc_string = N'' end select @rplc_string = @rplc_string + QUOTENAME(@table) exec @retcode = sp_MSsubst_filter_name N'<<TABLE>>', @rplc_string, @filter_clause output if @retcode <> 0 or @@error <> 0 begin return 1 end return 0 raiserror('Creating procedure sp_MSreplcheck_name', 0,1) GO CREATE PROCEDURE sp_MSreplcheck_name @name sysname, @raise_error bit = 1 AS declare @index int Set nocount on -- Name cannot be NULL or empty ("") -- Blank identifiers (" ") are allowed IF (@name is null OR datalength(@name) = 0) begin if @raise_error = 1 raiserror (15004,16,-1) return (1) end -- Check for proscribed characters declare @length int select @length = datalength( @name ) / 2 select @index = 1 while @index < @length begin if( 0 = unicode( substring( @name, @index, 1 ) ) ) begin if @raise_error = 1 raiserror(15006,16,-1,@name) return (1) end select @index = @index + 1 end --check for other proscribed characters select @index = charindex( N'%', @name) if (@index <> 0) begin if @raise_error = 1 raiserror(15006,16,-1,@name) return (1) end select @index = charindex(N'*', @name) if (@index <> 0) begin if @raise_error = 1 raiserror(15006,16,-1,@name) return (1) end select @index = charindex(N'[', @name) if (@index <> 0) begin if @raise_error = 1 raiserror(15006,16,-1,@name) return (1) end select @index = charindex(N']', @name) if (@index <> 0) begin if @raise_error = 1 raiserror(15006,16,-1,@name) return (1) end select @index = charindex(N'|', @name) if (@index <> 0) begin if @raise_error = 1 raiserror(15006,16,-1,@name) return (1) end select @index = charindex(N':', @name) if (@index <> 0) begin if @raise_error = 1 raiserror(15006,16,-1,@name) return (1) end select @index = charindex(N'"', @name) if (@index <> 0) begin if @raise_error = 1 raiserror(15006,16,-1,@name) return (1) end select @index = charindex(N'?', @name) if (@index <> 0) begin if @raise_error = 1 raiserror(15006,16,-1,@name) return (1) end /* ** Fix 52855 - allow single quote ** select @index = charindex(N'''', @name) if (@index <> 0) begin if @raise_error = 1 raiserror(15006,16,-1,@name) return (1) end */ select @index = charindex(N'\', @name) if (@index <> 0) begin if @raise_error = 1 raiserror(15006,16,-1,@name) return (1) end select @index = charindex(N'/', @name) if (@index <> 0) begin if @raise_error = 1 raiserror(15006,16,-1,@name) return (1) end select @index = charindex(N'<', @name) if (@index <> 0) begin if @raise_error = 1 raiserror(15006,16,-1,@name) return (1) end select @index = charindex(N'>', @name) if (@index <> 0) begin if @raise_error = 1 raiserror(15006,16,-1,@name) return (1) end -- return success return (0) GO exec dbo.sp_MS_marksystemobject sp_MSreplcheck_name go raiserror('Creating procedure sp_MScheckvalidsystables', 0,1) GO create procedure sp_MScheckvalidsystables @validsubs int output AS if not exists (select name from sysobjects where name='sysmergesubscriptions') begin set @validsubs = 0 return end /* Is there a valid non-loopback subscription? */ if exists (select * from sysmergesubscriptions where db_name=db_name() and srvid = (select srvid from master..sysservers where UPPER(srvname) = UPPER(@@servername) collate database_default) and subid <> partnerid) begin set @validsubs = 1 return end /* Only possible subscriptions are loopbacks. If database not enabled for publishing, ** then they don't indicate a valid publication/subscription. */ if not exists (select name from master..sysdatabases where (category & 4) = 4 and name = db_name() collate database_default) begin set @validsubs = 0 return end /* Database has merge publishing turned on, is probably a publisher. Look for loopback ** subscription just to be sure... */ if exists (select * from sysmergesubscriptions where db_name=db_name() and srvid = (select srvid from master..sysservers where UPPER(srvname) = UPPER(@@servername) collate database_default)) begin set @validsubs = 1 return end /* Must not be valid... */ set @validsubs = 0 return GO raiserror('Creating procedure sp_MSdrop_mergesystables', 0,1) GO create procedure sp_MSdrop_mergesystables as begin tran save transaction drop_mergesystables if exists (select * from sysobjects where name = 'sysmergearticles') begin drop table sysmergearticles end if @@error<>0 goto Error if exists (select * from sysobjects where name = 'sysmergepublications') begin drop table sysmergepublications end if @@error<>0 goto Error if exists (select * from sysobjects where name = 'sysmergesubscriptions') begin drop table sysmergesubscriptions end if @@error<>0 goto Error if exists (select * from sysobjects where name = 'MSmerge_contents') begin drop table MSmerge_contents end if @@error<>0 goto Error if exists (select * from sysobjects where name = 'MSmerge_replinfo') begin drop table MSmerge_replinfo end if @@error<>0 goto Error if exists (select * from sysobjects where name = 'MSmerge_identity_range ') begin drop table MSmerge_identity_range end if @@error<>0 goto Error if exists (select * from sysobjects where name = 'MSmerge_tombstone') begin drop table MSmerge_tombstone end if @@error<>0 goto Error if exists (select * from sysobjects where name = 'MSmerge_genhistory') begin drop table MSmerge_genhistory end if @@error<>0 goto Error if exists (select * from sysobjects where name = 'MSmerge_delete_conflicts') begin drop table MSmerge_delete_conflicts end if @@error<>0 goto Error if exists (select * from sysobjects where name = 'sysmergeschemachange') begin drop table sysmergeschemachange end if @@error<>0 goto Error if exists (select * from sysobjects where name = 'sysmergesubsetfilters') begin drop table sysmergesubsetfilters end if @@error<>0 goto Error if exists (select * from sysobjects where name = 'sysmergeschemaarticles') begin drop table sysmergeschemaarticles end if @@error<>0 goto Error if exists (select * from sysobjects where name = 'MSmerge_errorlineage') begin drop table MSmerge_errorlineage end if @@error<>0 goto Error if exists (select * from sysobjects where name = 'MSrepl_identity_range') begin drop table MSrepl_identity_range end if @@error<>0 goto Error if exists (select * from sysobjects where name = 'sysmergeextendedarticlesview') begin drop view sysmergeextendedarticlesview end if @@error<>0 goto Error if exists (select * from sysobjects where name = 'MSdynamicsnapshotjobs') begin drop table MSdynamicsnapshotjobs end if @@error<>0 goto Error if exists (select * from sysobjects where name = 'MSmerge_altsyncpartners') begin drop table MSmerge_altsyncpartners end if @@error<>0 goto Error if exists (select * from sysobjects where name = 'MSdynamicsnapshotviews') begin drop table MSdynamicsnapshotviews end if @@error<>0 goto Error if exists (select * from master..sysobjects where type='P' and name='sp_MSremovedebuginfrastructure') begin declare @retval int exec @retval= dbo.sp_MSremovedebuginfrastructure if @@ERROR <> 0 or @retval <> 0 goto Error end commit transaction return 0 Error: RAISERROR (20007, 16, -1) if @@trancount > 0 begin ROLLBACK TRANSACTION drop_mergesystables COMMIT TRANSACTION end return 1 go exec dbo.sp_MS_marksystemobject sp_MSdrop_mergesystables go raiserror ('Executing procedure dbo.sp_MSdrop_mergesystables.',0,1) go exec dbo.sp_MSdrop_mergesystables go dump tran master with no_log go raiserror('Creating procedure sp_MScreate_mergesystables',0,1) GO create procedure sp_MScreate_mergesystables as /* This is to make sure that the varbinary columns do not get padded */ set ANSI_PADDING off DECLARE @exist bit DECLARE @validsubs int select @exist = 1 begin tran save transaction MScreate_mergesystables exec dbo.sp_MScheckvalidsystables @validsubs output if @validsubs = 0 exec dbo.sp_MSdrop_mergesystables if not exists (select * from sysobjects where name = 'sysmergepublications') begin raiserror('Creating table sysmergepublications',0,1) create table dbo.sysmergepublications ( publisher sysname NOT NULL default @@servername, publisher_db sysname NOT NULL default db_name(), name sysname NOT NULL, description nvarchar(255) NULL, retention int NULL, publication_type tinyint NULL, pubid uniqueidentifier NOT NULL, designmasterid uniqueidentifier NULL, parentid uniqueidentifier NULL, sync_mode tinyint NULL, allow_push int NULL, allow_pull int NULL, allow_anonymous int NULL, centralized_conflicts int NULL, status tinyint NULL, snapshot_ready tinyint NULL, enabled_for_internet bit NOT NULL default 0, dynamic_filters bit NOT NULL default 0, -- portable snapshot support snapshot_in_defaultfolder bit NOT NULL default 1, alt_snapshot_folder nvarchar(255) NULL, -- Pre/post - snapshot commands pre_snapshot_script nvarchar(255) NULL, post_snapshot_script nvarchar(255) NULL, -- Snapshot compression compress_snapshot bit NOT NULL default 0, -- Post 7.0 Ftp support ftp_address sysname NULL, ftp_port int NOT NULL default 21, ftp_subdirectory nvarchar(255) NULL, ftp_login sysname NULL default N'anonymous', ftp_password nvarchar(524) NULL, conflict_retention int NULL, keep_before_values int NULL default 0, allow_subscription_copy bit NULL default 0, allow_synctoalternate bit NULL default 0, validate_subscriber_info nvarchar(500) NULL, ad_guidname sysname NULL, backward_comp_level int not NULL default 10, --7.0 RTM max_concurrent_merge int not NULL default 0, max_concurrent_dynamic_snapshots int not NULL default 0 ) if @@ERROR <> 0 goto Error CREATE UNIQUE NONCLUSTERED INDEX nc1sysmergepublications ON sysmergepublications(pubid) if @@ERROR <> 0 goto Error exec dbo.sp_MS_marksystemobject sysmergepublications if @@ERROR <> 0 goto Error -- grant select on sysmergepublications to public end if not exists (select * from sysobjects where name = 'MSmerge_errorlineage') begin raiserror('Creating table MSmerge_errorlineage',0,1) create table dbo.MSmerge_errorlineage ( tablenick int NOT NULL, rowguid uniqueidentifier NOT NULL, lineage varbinary(255) ) exec dbo.sp_MS_marksystemobject MSmerge_errorlineage if @@ERROR <> 0 goto Error create unique clustered index uc1errorlineage on MSmerge_errorlineage(tablenick, rowguid) if @@ERROR <> 0 goto Error --grant select on MSmerge_errorlineage to public end -- this table exists at distribution/db and subscriber databse both if not exists (select * from sysobjects where name = 'MSrepl_identity_range') begin raiserror('Creating table MSrepl_identity_range',0,1) create table dbo.MSrepl_identity_range ( objid int not NULL primary key, next_seed bigint NULL, --resource control pub_range bigint NULL, --publisher range range bigint NULL, -- set by sp_addmergearticle max_identity bigint NULL, --resource control threshold int NULL, --in percentage, set by sp_addmergearticle current_max bigint NULL --max value for current check constraint,set by sp_addmergearticle ) exec dbo.sp_MS_marksystemobject MSrepl_identity_range if @@ERROR <> 0 goto Error --grant select on MSrepl_identity_range to public end if not exists (select * from sysobjects where name = 'sysmergearticles') begin raiserror('Creating table sysmergearticles',0,1) create table dbo.sysmergearticles ( name sysname NOT NULL, type tinyint NULL, objid int NOT NULL, sync_objid int NOT NULL, view_type tinyint NULL, artid uniqueidentifier NOT NULL, description nvarchar(255) NULL, pre_creation_command tinyint NULL, pubid uniqueidentifier NOT NULL, nickname int NOT NULL, column_tracking int NOT NULL, status tinyint NULL, conflict_table sysname NULL, creation_script nvarchar(255) NULL, conflict_script nvarchar(255) NULL, article_resolver nvarchar(255) NULL, ins_conflict_proc sysname NULL, insert_proc sysname NULL, update_proc sysname NULL, select_proc sysname NULL, schema_option binary(8) NULL, destination_object sysname NOT NULL, destination_owner sysname NULL, resolver_clsid nvarchar(50) NULL, subset_filterclause nvarchar(1000) NULL, missing_col_count int NULL, missing_cols varbinary(128) NULL, excluded_cols varbinary(128) NULL, excluded_col_count int not NULL default 0, columns varbinary(128) NULL, resolver_info nvarchar(255) NULL, view_sel_proc nvarchar(290) NULL, gen_cur int NULL, vertical_partition int not NULL default 0, identity_support int not NULL default 0, before_image_objid int NULL, before_view_objid int NULL, verify_resolver_signature int NULL, allow_interactive_resolver bit NOT NULL default 0, fast_multicol_updateproc bit NOT NULL default 0, check_permissions int NOT NULL default 0, maxversion_at_cleanup int NOT NULL default 1, published_in_tran_pub bit NOT NULL default 0 -- Note: Please update sysmergeextendedarticlesview whenever -- there is a schema change in sysmergearticles ) if @@error<>0 goto Error else begin create unique clustered index uc1sysmergearticles on sysmergearticles(artid, pubid) if @@ERROR <> 0 goto Error if not exists (select * from sysindexes where name = 'nc1sysmergearticles') begin create nonclustered index nc1sysmergearticles on sysmergearticles(nickname) if @@ERROR <> 0 return 1 end end exec dbo.sp_MS_marksystemobject sysmergearticles if @@ERROR <> 0 goto Error grant select(nickname,gen_cur,maxversion_at_cleanup) on sysmergearticles to public end if not exists (select * from sysobjects where name = 'sysmergeschemaarticles') begin -- The extended merge articles table is for storing -- schema only article information. -- The current supported schema only articles are -- stored procs and views. raiserror('Creating table sysmergeschemaarticles',0,1) create table dbo.sysmergeschemaarticles ( name sysname NOT NULL, type tinyint NULL, objid int NOT NULL, artid uniqueidentifier NOT NULL, description nvarchar(255) NULL, pre_creation_command tinyint NULL, pubid uniqueidentifier NOT NULL, status tinyint NULL, creation_script nvarchar(255) NULL, schema_option binary(8) NULL, destination_object sysname NOT NULL, destination_owner sysname NULL -- Note: Please update sysmergeextendedarticlesview whenever -- there is a schema change in sysmergeschemaarticles ) if @@error<>0 goto Error else begin create unique clustered index uc1sysmergeschemaarticles on sysmergeschemaarticles(artid, pubid) if @@ERROR <> 0 goto Error end exec dbo.sp_MS_marksystemobject sysmergeschemaarticles if @@ERROR <> 0 goto Error end if exists (select * from sysobjects where name = 'sysmergeextendedarticlesview') begin drop view dbo.sysmergeextendedarticlesview end exec ('create view dbo.sysmergeextendedarticlesview as select name, type, objid, sync_objid, view_type, artid, description, pre_creation_command, pubid, nickname, column_tracking, status, conflict_table, creation_script, conflict_script, article_resolver, ins_conflict_proc, insert_proc, update_proc, select_proc, schema_option, destination_object, resolver_clsid, subset_filterclause, missing_col_count, missing_cols, columns, resolver_info, view_sel_proc, gen_cur, excluded_cols, excluded_col_count, vertical_partition, identity_support, destination_owner, before_image_objid, before_view_objid, verify_resolver_signature, allow_interactive_resolver, fast_multicol_updateproc, check_permissions, maxversion_at_cleanup, published_in_tran_pub from sysmergearticles union all select name, type, objid, NULL, NULL, artid, description, pre_creation_command, pubid, NULL, NULL, status, NULL, creation_script, NULL, NULL, NULL, NULL, NULL, NULL, schema_option, destination_object, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, destination_owner, NULL, NULL, NULL, 0, 0, 0, NULL, 0 from sysmergeschemaarticles go') if @@error <> 0 goto Error exec dbo.sp_MS_marksystemobject sysmergeextendedarticlesview if not exists (select * from sysobjects where name = 'sysmergesubscriptions') begin raiserror('Creating table sysmergesubscriptions',0,1) create table dbo.sysmergesubscriptions ( subid uniqueidentifier NOT NULL, partnerid uniqueidentifier NOT NULL, datasource_type int NOT NULL, datasource_path nvarchar(255) NULL, srvid int NOT NULL, db_name sysname NOT NULL constraint unique_pubsrvdb unique nonclustered (pubid, srvid, db_name), pubid uniqueidentifier NULL, status tinyint NOT NULL, subscriber_type int NOT NULL, subscription_type int NOT NULL, priority real NOT NULL, sync_type tinyint NOT NULL, -- 1 = automatic 2 = no sync description nvarchar(255) NULL, login_name sysname NOT NULL, last_validated datetime NULL, subscriber_server sysname NULL, use_interactive_resolver bit NOT NULL default 0, publication sysname NULL, distributor sysname NULL, validation_level int not NULL default 0, resync_gen int not NULL default -1, attempted_validate datetime NULL, last_sync_date datetime NULL, last_sync_status int NULL, last_sync_summary sysname NULL ) if @@error<>0 goto Error else begin create unique clustered index uc1sysmergesubscriptions on sysmergesubscriptions (subid) if @@ERROR<>0 goto Error create index nc2sysmergesubscriptions on sysmergesubscriptions (srvid, db_name) if @@ERROR<>0 goto Error end exec dbo.sp_MS_marksystemobject sysmergesubscriptions if @@ERROR <> 0 goto Error --grant select on sysmergesubscriptions to public end if not exists (select * from sysobjects where name = 'MSmerge_replinfo') begin raiserror('Creating table MSmerge_replinfo',0,1) create table dbo.MSmerge_replinfo ( repid uniqueidentifier NOT NULL, replnickname int NOT NULL, recgen int NULL, recguid uniqueidentifier NULL, sentgen int NULL, sentguid uniqueidentifier NULL, schemaversion int NULL, schemaguid uniqueidentifier NULL, merge_jobid binary(16) NULL, snapshot_jobid binary(16) NULL ) if @@ERROR <> 0 goto Error else begin create unique clustered index uc1MSmerge_replinfo on MSmerge_replinfo (repid) if @@ERROR <> 0 goto Error end exec dbo.sp_MS_marksystemobject MSmerge_replinfo if @@ERROR <> 0 goto Error --grant select on MSmerge_replinfo to public end if not exists (select * from sysobjects where name = 'MSmerge_tombstone') begin raiserror('Creating table MSmerge_tombstone',0,1) create table dbo.MSmerge_tombstone ( rowguid uniqueidentifier rowguidcol NOT NULL, tablenick int NOT NULL, type tinyint NOT NULL, lineage varbinary(249) NOT NULL, generation int NOT NULL, reason nvarchar(255) NOT NULL, ) if @@ERROR <> 0 goto Error else begin create unique clustered index uc1MSmerge_tombstone on MSmerge_tombstone (tablenick DESC, rowguid) if @@ERROR <> 0 goto Error create index nc2MSmerge_tombstone on MSmerge_tombstone (generation) if @@ERROR <> 0 goto Error end exec dbo.sp_MS_marksystemobject MSmerge_tombstone if @@ERROR <> 0 goto Error --grant select on MSmerge_tombstone to public end if not exists (select * from sysobjects where name = 'MSmerge_contents') begin raiserror('Creating table MSmerge_contents',0,1) create table dbo.MSmerge_contents ( tablenick int NOT NULL, rowguid uniqueidentifier rowguidcol NOT NULL, generation int NOT NULL, partchangegen int NULL, joinchangegen int NULL, lineage varbinary(249) NOT NULL, colv1 varbinary(2048) NULL, ) if @@ERROR <> 0 goto Error else begin create unique clustered index uc1SycContents on MSmerge_contents(tablenick, rowguid) if @@ERROR <> 0 goto Error create index nc2MSmerge_contents on MSmerge_contents(generation) if @@ERROR <> 0 goto Error create index nc3MSmerge_contents on MSmerge_contents(partchangegen) if @@ERROR <> 0 goto Error create index nc4MSmerge_contents on MSmerge_contents(rowguid) if @@ERROR <> 0 goto Error end exec dbo.sp_MS_marksystemobject MSmerge_contents if @@ERROR <> 0 goto Error --grant select on MSmerge_contents to public end if not exists (select * from sysobjects where name = 'MSmerge_genhistory') begin raiserror('Creating table MSmerge_genhistory',0,1) create table dbo.MSmerge_genhistory ( guidsrc uniqueidentifier NOT NULL, guidlocal uniqueidentifier NOT NULL, pubid uniqueidentifier NULL, generation int NOT NULL, art_nick int NULL, nicknames varbinary(1000) NOT NULL, coldate datetime NOT NULL ) if @@ERROR <> 0 goto Error create clustered index c1MSmerge_genhistory on MSmerge_genhistory(generation) if @@ERROR <> 0 goto Error create unique index unc1MSmerge_genhistory on MSmerge_genhistory(guidsrc, pubid) if @@ERROR <> 0 goto Error create index nc2MSmerge_genhistory on MSmerge_genhistory(guidlocal) if @@ERROR <> 0 goto Error CREATE INDEX nc4MSmerge_genhistory ON MSmerge_genhistory(coldate) if @@ERROR <> 0 goto Error exec dbo.sp_MS_marksystemobject MSmerge_genhistory if @@ERROR <> 0 goto Error --grant select on MSmerge_genhistory to public end if not exists (select * from sysobjects where name = 'MSmerge_delete_conflicts') begin raiserror('Creating table MSmerge_delete_conflicts',0,1) create table dbo.MSmerge_delete_conflicts ( tablenick int NOT NULL, rowguid uniqueidentifier rowguidcol NOT NULL, origin_datasource nvarchar(255) NULL, conflict_type int NULL, reason_code int NULL, reason_text nvarchar(720) NULL, pubid uniqueidentifier NULL, create_time datetime not null default getdate() ) if @@ERROR <> 0 goto Error else begin create clustered index uc1MSmerge_delete_conflicts on MSmerge_delete_conflicts(tablenick, rowguid) if @@ERROR <> 0 goto Error end CREATE UNIQUE NONCLUSTERED INDEX nc1MSmerge_delete_conflicts ON MSmerge_delete_conflicts(tablenick, rowguid, origin_datasource) if @@ERROR <> 0 goto Error exec dbo.sp_MS_marksystemobject MSmerge_delete_conflicts if @@ERROR <> 0 goto Error --grant select on MSmerge_delete_conflicts to public end if not exists (select * from sysobjects where name = 'sysmergeschemachange') begin raiserror('Creating table sysmergeschemachange',0,1) create table dbo.sysmergeschemachange ( pubid uniqueidentifier NOT NULL, artid uniqueidentifier NULL, schemaversion int NOT NULL, schemaguid uniqueidentifier NOT NULL, schematype int NOT NULL, schematext nvarchar(2000) NOT NULL ) if @@ERROR <> 0 goto Error else begin create unique clustered index schemachangeversion on sysmergeschemachange(schemaversion, pubid) if @@ERROR <> 0 goto Error end exec dbo.sp_MS_marksystemobject sysmergeschemachange if @@ERROR <> 0 goto Error --grant select on sysmergeschemachange to public end if not exists (select * from sysobjects where name = 'sysmergesubsetfilters') begin raiserror('Creating table sysmergesubsetfilters',0,1) create table dbo.sysmergesubsetfilters ( filtername sysname NOT NULL, join_filterid int identity NOT NULL, pubid uniqueidentifier NOT NULL, artid uniqueidentifier NOT NULL, art_nickname int NOT NULL, join_articlename sysname NOT NULL, join_nickname int NOT NULL, join_unique_key int NOT NULL, expand_proc sysname NULL, join_filterclause nvarchar(1000) NULL ) if @@ERROR <> 0 goto Error CREATE UNIQUE NONCLUSTERED INDEX nc1sysmergesubsetfilters ON sysmergesubsetfilters(join_filterid, pubid) if @@ERROR <> 0 goto Error exec dbo.sp_MS_marksystemobject sysmergesubsetfilters if @@ERROR <> 0 goto Error --grant select on sysmergesubsetfilters to public end if @@error <> 0 goto Error if not exists (select * from sysobjects where name = 'MSdynamicsnapshotviews') begin raiserror('Creating table MSdynamicsnapshotviews',0,1) create table dbo.MSdynamicsnapshotviews ( dynamic_snapshot_view_name sysname primary key ) if @@ERROR <> 0 goto Error exec dbo.sp_MS_marksystemobject MSdynamicsnapshotviews end if not exists (select * from sysobjects where name = 'MSdynamicsnapshotjobs') begin raiserror('Creating table MSdynamicsnapshotjobs',0,1) create table dbo.MSdynamicsnapshotjobs ( id int identity, name sysname not null unique, pubid uniqueidentifier not null, job_id uniqueidentifier not null, dynamic_filter_login sysname null, dynamic_filter_hostname sysname null, dynamic_snapshot_location nvarchar(255) not null ) if @@ERROR <> 0 goto Error exec dbo.sp_MS_marksystemobject MSdynamicsnapshotjobs create unique clustered index uciMSdynamicsnapshotjobs on dbo.MSdynamicsnapshotjobs(job_id, pubid) if @@ERROR <> 0 goto Error end if @@error <> 0 goto Error if not exists (select * from sysobjects where name = 'MSmerge_altsyncpartners') begin raiserror('Creating table MSmerge_altsyncpartners',0,1) create table dbo.MSmerge_altsyncpartners ( subid uniqueidentifier not null, alternate_subid uniqueidentifier not null, description nvarchar(255) NULL ) if @@ERROR <> 0 goto Error exec dbo.sp_MS_marksystemobject MSmerge_altsyncpartners create unique clustered index uciMSmerge_altsyncpartners on dbo.MSmerge_altsyncpartners(subid, alternate_subid) if @@ERROR <> 0 goto Error end if exists (select * from master..sysobjects where type='P' and name='sp_MScreatedebuginfrastructure') begin declare @retval int exec @retval= dbo.sp_MScreatedebuginfrastructure if @@ERROR <> 0 or @retval <> 0 goto Error end commit transaction return (0) Error: if @@trancount > 0 begin ROLLBACK TRANSACTION MScreate_mergesystables COMMIT TRANSACTION end RAISERROR (20008, 16, -1) return (1) go exec dbo.sp_MS_marksystemobject sp_MScreate_mergesystables go raiserror('Creating procedure sp_MStestbit',0,1) go create procedure sp_MStestbit @bm varbinary(128), @coltotest smallint AS declare @word smallint declare @bit smallint declare @mask binary(2) declare @mval int declare @oldword binary(2) if @coltotest < 1 return 0 SELECT @word = 1 + FLOOR((@coltotest -1)/16) SELECT @bit = (@coltotest -1) % 16 SELECT @mval = POWER(2, @bit) SELECT @mask = convert( binary(2), unicode( substring( convert( nchar(2), convert( binary(4), @mval ) ), 2, 1 ) ) ) SELECT @oldword = convert( binary(2), SUBSTRING( convert( nvarchar(64),@bm), @word, 1) ) IF @oldword IS NULL return 0 return convert( smallint, @oldword ) & convert( smallint, @mask ) go exec dbo.sp_MS_marksystemobject sp_MStestbit go grant exec on dbo.sp_MStestbit to public raiserror('Creating procedure sp_MSsetbit',0,1) go set ansi_padding on go create procedure sp_MSsetbit @bm varbinary(128) output, @coltoadd smallint, @toset int = 1 AS declare @bytenum smallint declare @bit smallint declare @mask tinyint declare @newbyte tinyint declare @oldbyte tinyint SELECT @bytenum = 1 + FLOOR((@coltoadd-1)/8) IF @bytenum > 128 return 0 SELECT @bit = (@coltoadd-1) % 8 SET @mask = POWER(2, @bit) if @toset = 0 SET @mask = (~@mask % 256) if @bm is null set @bm = 0x0 while datalength(@bm) < @bytenum set @bm = @bm + 0x00 SET @oldbyte = SUBSTRING( @bm, @bytenum, 1) IF @oldbyte IS NULL SET @oldbyte = 0 if @toset <> 0 SET @newbyte = @oldbyte | @mask else SET @newbyte = @oldbyte & @mask if (@bytenum = 1) set @bm = convert(binary(1), @newbyte) + substring(@bm, 2, 127) else set @bm = substring(@bm, 1, @bytenum - 1) + convert(binary(1), @newbyte) + substring(@bm, @bytenum + 1, 128 - @bytenum) go exec dbo.sp_MS_marksystemobject sp_MSsetbit go grant exec on dbo.sp_MSsetbit to public raiserror('Creating procedure sp_MSinsertcontents',0,1) go create procedure sp_MSinsertcontents @tablenick int, @rowguid uniqueidentifier, @lineage varbinary(249), @colv1 varbinary(2048) AS /* ** permission check */ declare @retcode int declare @objid int declare @owner sysname declare @artid uniqueidentifier declare @guidstr nvarchar(32) declare @instrigger nvarchar(270) select @objid = objid, @artid=artid from sysmergearticles where nickname=@tablenick select @owner =user_name(uid) from sysobjects where id=@objid exec @retcode=sp_MSguidtostr @artid, @guidstr out if @retcode<>0 or @@ERROR<>0 return (1) set @instrigger = QUOTENAME(@owner) + '.ins_' + @guidstr if trigger_nestlevel(object_id(@instrigger)) = 0 begin raiserror(14126, 16, -1) return (1) -- current user does not have insert permission to underlying table end insert into MSmerge_contents (tablenick, rowguid, generation, partchangegen, joinchangegen, lineage, colv1) values (@tablenick, @rowguid, 0, 0, 0, @lineage, @colv1) if @@error <> 0 begin raiserror (20041, 16, -1) return (1) end delete from MSmerge_tombstone where rowguid = @rowguid and tablenick = @tablenick if @@error <> 0 begin raiserror (20041, 16, -1) return (1) end go exec dbo.sp_MS_marksystemobject sp_MSinsertcontents go raiserror('Creating procedure sp_MSupdatecontents',0,1) go create procedure sp_MSupdatecontents @tablenick int, @rowguid uniqueidentifier, @lineage varbinary(249), @colv1 varbinary(2048), @partchange int = null, @joinchange int = null AS /* ** permission check */ declare @retcode int declare @objid int declare @owner sysname declare @artid uniqueidentifier declare @guidstr nvarchar(32) declare @updtrigger nvarchar(270) select @objid = objid, @artid=artid from sysmergearticles where nickname=@tablenick select @owner =user_name(uid) from sysobjects where id=@objid exec @retcode=sp_MSguidtostr @artid, @guidstr out if @retcode<>0 or @@ERROR<>0 return (1) set @updtrigger = QUOTENAME(@owner) + '.upd_' + @guidstr if trigger_nestlevel(object_id(@updtrigger)) = 0 begin raiserror(14126, 16, -1) return (1) -- current user does not 'update all' permission upon underlying table end update MSmerge_contents set lineage = @lineage, generation = 0, colv1 = @colv1 where tablenick = @tablenick and rowguid = @rowguid if (@@rowcount = 0) insert into MSmerge_contents (tablenick, rowguid, generation, joinchangegen, lineage, colv1) values (@tablenick, @rowguid, 0, 1, @lineage, @colv1) if @@error <> 0 begin raiserror (20041, 16, -1) return (1) end if @partchange = 1 begin update MSmerge_contents set partchangegen = 0, joinchangegen = 0 where tablenick = @tablenick and rowguid = @rowguid if @@error <> 0 begin raiserror (20041, 16, -1) return (1) end end else if @joinchange = 1 begin update MSmerge_contents set joinchangegen = 0 where tablenick = @tablenick and rowguid = @rowguid if @@error <> 0 begin raiserror (20041, 16, -1) return (1) end end go exec dbo.sp_MS_marksystemobject sp_MSupdatecontents go raiserror(15339, -1, -1, 'sp_MSdeletecontents') go create procedure sp_MSdeletecontents @tablenick int, @rowguid uniqueidentifier AS declare @nick int declare @reason nvarchar(255) declare @lineage varbinary(255) /* ** permission check */ declare @retcode int declare @objid int declare @owner sysname declare @artid uniqueidentifier declare @guidstr nvarchar(32) declare @deltrigger nvarchar(270) declare @oldmaxversion int select @objid = objid, @artid=artid from sysmergearticles where nickname=@tablenick select @owner =user_name(uid) from sysobjects where id=@objid exec @retcode=sp_MSguidtostr @artid, @guidstr out if @retcode<>0 or @@ERROR<>0 return (1) set @deltrigger = QUOTENAME(@owner) + '.del_' + @guidstr if trigger_nestlevel(object_id(@deltrigger)) = 0 begin raiserror(14126, 16, -1) return (1) -- current user does not have 'delete' permission to underlying table end exec dbo.sp_MSgetreplnick @nickname = @nick out if (@@error <> 0) or @nick IS NULL begin RAISERROR (14055, 11, -1) RETURN(1) end select @oldmaxversion= maxversion_at_cleanup from sysmergearticles where nickname = @tablenick select @lineage = lineage from MSmerge_contents (UPDLOCK ROWLOCK index = 1) where tablenick = @tablenick and rowguid = @rowguid set @lineage= { fn UPDATELINEAGE(@lineage, @nick, @oldmaxversion+1) } select @reason = 'user delete' insert into MSmerge_tombstone (rowguid, tablenick, type, lineage, generation, reason) values (@rowguid, @tablenick, 1, @lineage, 0, @reason) if @@error <> 0 begin raiserror (20041, 16, -1) return (1) end delete from MSmerge_contents where tablenick = @tablenick and rowguid = @rowguid if @@error <> 0 begin raiserror (20041, 16, -1) return (1) end go exec dbo.sp_MS_marksystemobject sp_MSdeletecontents go raiserror('Creating procedure sp_MSunmarkifneeded',0,1) GO CREATE PROCEDURE sp_MSunmarkifneeded( @object sysname, @pubid uniqueidentifier, @pre_command int = 0, @publisher sysname, @publisher_db sysname )AS declare @table_in_use int declare @retcode int select @table_in_use = 0 --if pre-creation_command is 'drop (1)' or 'truncate (3)', then disallow this deployment if there is already an article using that table. --other commands like 'delete, truncate, none are fine' if exists (select * from sysmergearticles where objid=object_id(@object) and pubid in (select pubid from sysmergepublications where LOWER(publisher)=LOWER(@publisher) and publisher_db=@publisher_db and pubid<>@pubid)) OR ((@pre_command=1 or @pre_command=3) and EXISTS (select * from sysmergearticles where objid=object_id(@object) and pubid <> @pubid and pubid not in (select pubid from sysmergepublications where LOWER(publisher)=LOWER(@@SERVERNAME) and publisher_db=db_name()))) begin select @table_in_use = 1 select @table_in_use return (0) end exec @retcode = sp_MSunmarkreplinfo @object if @retcode <>0 or @@error<>0 return (1) select @table_in_use return (0) GO exec dbo.sp_MS_marksystemobject sp_MSunmarkifneeded go grant exec on dbo.sp_MSunmarkifneeded to public go raiserror('Creating procedure sp_MSunmarkreplinfo',0,1) GO CREATE PROCEDURE sp_MSunmarkreplinfo( @object sysname, /* Name of the table, unqualitied */ @owner sysname = NULL, /* Name of the owner, unqualified */ @type smallint = 0 /* default is to unmark, as name implies */ )AS declare @merge_pub_object_bit int declare @merge_pub_unmark_bit int declare @id int declare @qualified_name nvarchar(270) declare @retcode int exec @retcode = sp_MSreplcheck_subscribe if @@error<>0 or @retcode<>0 return (1) if @owner is NULL or @owner='' select @owner = user_name(uid) from sysobjects where name=@object select @qualified_name = QUOTENAME(@owner) + '.' + QUOTENAME(@object) select @id = object_id(@qualified_name) select @merge_pub_object_bit = 128 select @merge_pub_unmark_bit = ~@merge_pub_object_bit if exists (select name from sysobjects where id = @id) begin if @type = 0 /* type = 0, unmark; else mark the bit */ begin BEGIN TRANSACTION exec dbo.sp_replupdateschema @qualified_name update sysobjects set replinfo = replinfo & @merge_pub_unmark_bit where id = @id exec dbo.sp_replupdateschema @qualified_name COMMIT TRANSACTION end else begin BEGIN TRANSACTION exec dbo.sp_replupdateschema @qualified_name update sysobjects set replinfo = replinfo | @merge_pub_object_bit where id = @id exec dbo.sp_replupdateschema @qualified_name COMMIT TRANSACTION end end GO exec dbo.sp_MS_marksystemobject sp_MSunmarkreplinfo go grant execute on dbo.sp_MSunmarkreplinfo to public go /* ** This is to have a better name 'sp_MSmarkreplinfo' while keeping the change minimal. */ raiserror('Creating procedure sp_MSmarkreplinfo',0,1) GO CREATE PROCEDURE sp_MSmarkreplinfo( @object sysname, /* Name of the table, unqualitied */ @owner sysname = NULL /* Name of the owner, unqualified */ )AS declare @retcode int exec @retcode = sp_MSunmarkreplinfo @object, @owner, 1 if @@ERROR<>0 or @retcode<>0 return (1) return (0) GO exec dbo.sp_MS_marksystemobject sp_MSmarkreplinfo go raiserror('Creating procedure sp_MSunmarkschemaobject',0,1) go CREATE PROCEDURE sp_MSunmarkschemaobject( @object sysname, @owner sysname = NULL )AS begin set nocount on declare @schema_obj_bit_mask int declare @qualified_name nvarchar(520) declare @id int declare @retcode int exec @retcode = sp_MSreplcheck_subscribe if @@error<>0 or @retcode <>0 return (1) select @schema_obj_bit_mask = 0x00000200 select @schema_obj_bit_mask = ~@schema_obj_bit_mask if (@owner is null or @owner = N'') begin select @owner = user_name() end select @qualified_name = QUOTENAME(@owner) + '.' + QUOTENAME(@object) select @id = NULL select @id = object_id(@qualified_name) if (@id is not null) begin begin transaction exec dbo.sp_replupdateschema @qualified_name update sysobjects set replinfo = replinfo & @schema_obj_bit_mask where id = @id exec dbo.sp_replupdateschema @qualified_name commit transaction end return 0 end go exec dbo.sp_MS_marksystemobject sp_MSunmarkschemaobject go grant execute on dbo.sp_MSunmarkschemaobject to public go raiserror('Creating procedure sp_MSmarkschemaobject',0,1) go CREATE PROCEDURE sp_MSmarkschemaobject( @object sysname, @owner sysname = NULL )AS begin set nocount on declare @schema_obj_bit_mask int declare @qualified_name nvarchar(520) declare @id int declare @retcode int exec @retcode = sp_MSreplcheck_subscribe if @@error<>0 or @retcode<>0 return (1) select @schema_obj_bit_mask = 0x00000200 if (@owner is null or @owner = N'') begin select @owner = user_name() end select @qualified_name = QUOTENAME(@owner) + '.' + QUOTENAME(@object) select @id = NULL select @id = object_id(@qualified_name) if (@id is not null) begin begin transaction exec dbo.sp_replupdateschema @qualified_name update sysobjects set replinfo = replinfo | @schema_obj_bit_mask where id = @id exec dbo.sp_replupdateschema @qualified_name commit transaction end return 0 end go exec dbo.sp_MS_marksystemobject sp_MSmarkschemaobject go raiserror('Creating procedure sp_MSaddanonymousreplica',0,1) GO CREATE PROCEDURE sp_MSaddanonymousreplica (@publication sysname, @publisher sysname, @publisherDB sysname, @anonymous int, @sync_type int = 1, /* sync type is automatic by default */ @preexists bit=0 OUTPUT ) as set nocount on declare @retcode int declare @subscription_type nvarchar(15) declare @sync_typestr nvarchar(15) declare @sub_typeid int declare @pubid uniqueidentifier /* ** need more than PAL to do this. */ exec @retcode = sp_MSreplcheck_subscribe if @@error<>0 or @retcode<>0 return (1) select @preexists = 0 if @anonymous = 1 begin select @subscription_type = 'anonymous' select @sub_typeid = 2 --subscription type value for anonymous end else begin select @subscription_type = 'local' select @sub_typeid = 1 --subscription type value for well known pull end if @sync_type = 1 select @sync_typestr = 'automatic' else select @sync_typestr = 'none' -- this change is made so that we will try to add pull/anonymous subscriptions, even if -- there is a already a subscription for that publication, however the subscription type -- does not match. In this way we can prevent users from using incorrect subscription type -- through command line or merge control. if exists (select * from sysobjects where name='sysmergepublications') begin select @pubid=pubid from sysmergepublications where name=@publication and UPPER(publisher)=UPPER(@publisher) and publisher_db = @publisherDB if @pubid is not NULL begin /* Check if theres is a subscriptions entry that matches the pubid and current subscription with the right type */ if exists (select * from sysmergesubscriptions where pubid =@pubid and UPPER(subscriber_server) = @@SERVERNAME and db_name = DB_NAME() and subscription_type=@sub_typeid) begin select @preexists = 1 return (0) -- replica exists. end /* ** Check if theres is a subscriptions entry that matches the pubid and current subscription - ** If there is a match and the types are not the same, then return appropriate error. */ else if exists (select * from sysmergesubscriptions where pubid =@pubid and UPPER(subscriber_server) = @@SERVERNAME and db_name = DB_NAME()) begin RAISERROR (21500, 16, -1, @publication) -- replica exists with wrong subscription type select @preexists = 1 return (1) end end end -- Call this SP to add this replica exec @retcode = dbo.sp_addmergepullsubscription @publication = @publication, @publisher = @publisher, @publisher_db=@publisherDB, @subscriber_type =@subscription_type, @sync_type = @sync_typestr IF @retcode<>0 or @@ERROR<>0 return (1) return (0) GO exec dbo.sp_MS_marksystemobject sp_MSaddanonymousreplica go grant execute on dbo.sp_MSaddanonymousreplica to public go raiserror('Creating procedure sp_MSgetreplicainfo',0,1) GO CREATE PROCEDURE sp_MSgetreplicainfo (@publisher sysname, @publisher_db sysname, @publication sysname, @datasource_type int = 0, /* 0 = SQL Server, 1 = DSN, 2 = Jet */ @server_name sysname = NULL, /* Server Name */ @db_name sysname = NULL, /* Database Name */ @datasource_path nvarchar(255) = NULL) /* Datasource path - JET MDB file path etc */ as declare @srvid int declare @retcode int declare @repid uniqueidentifier declare @pubid uniqueidentifier declare @schemaguid uniqueidentifier declare @nickname int declare @subscription_type int declare @validation_level int declare @reptype tinyint declare @priority real declare @schversion int declare @status int declare @resync_gen int declare @partnerid uniqueidentifier declare @sync_type tinyint declare @description nvarchar(255) declare @distributor sysname /* ** Parameter Check: @publication. ** Make sure that the publication exists. */ if (@publication is null) begin RAISERROR(14043, 16, -1, '@publication') return (1) end if (@server_name is NULL) SET @server_name = @@SERVERNAME if (@db_name is NULL) set @db_name = db_name() SELECT @srvid = srvid FROM master..sysservers WHERE UPPER(srvname) = UPPER(@server_name) collate database_default IF @@ERROR <> 0 BEGIN RAISERROR (14080, 16, -1) RETURN (1) END IF @srvid IS NULL BEGIN RAISERROR (14010, 16, -1) RETURN (1) END select @pubid = pubid from sysmergepublications where name = @publication and UPPER(publisher)=UPPER(@publisher) and publisher_db=@publisher_db if (@pubid is null) begin RAISERROR (20026, 16, -1, @publication) return (1) end if (@datasource_type = 0) begin SELECT @repid = subid, @priority = priority, @reptype = subscriber_type, @subscription_type = subscription_type , @status = status, @partnerid = partnerid, @sync_type = sync_type, @description = description, @distributor = distributor, @validation_level=validation_level, @resync_gen=resync_gen FROM sysmergesubscriptions WHERE srvid = @srvid and db_name = @db_name and pubid = @pubid END ELSE BEGIN SELECT @repid = subid, @priority = priority, @reptype = subscriber_type, @subscription_type = subscription_type , @status = status, @partnerid = partnerid, @sync_type = sync_type, @description = description,@distributor = distributor, @validation_level=validation_level, @resync_gen=resync_gen FROM sysmergesubscriptions WHERE srvid = @srvid and pubid = @pubid END if @repid is NULL begin RAISERROR(20021, 16, -1) return (1) end select @schversion = schemaversion, @schemaguid = schemaguid from MSmerge_replinfo where repid = @repid select @nickname = replnickname from MSmerge_replinfo where repid = @repid select @repid, @nickname, @reptype, @subscription_type, @priority, @schversion, @schemaguid, @status, @partnerid, @sync_type, @description, @publication, @distributor, @validation_level, @resync_gen return (0) go exec dbo.sp_MS_marksystemobject sp_MSgetreplicainfo go grant execute on dbo.sp_MSgetreplicainfo to public raiserror('Creating procedure sp_MSadd_repl_job',0,1) go CREATE PROCEDURE sp_MSadd_repl_job @name nvarchar(200), @subsystem nvarchar(60) = 'TSQL', @server sysname = NULL, @username sysname = NULL, @databasename sysname = NULL, @enabled TINYINT = 0, @freqtype INT = 2, -- 2 means OnDemand @freqinterval INT = 1, @freqsubtype INT = 1, @freqsubinterval INT = 1, @freqrelativeinterval INT = 1, @freqrecurrencefactor INT = 1, @activestartdate INT = 0, @activeenddate INT = 0, @activestarttimeofday INT = 0, @activeendtimeofday INT = 0, @nextrundate INT = 0, @nextruntime INT = 0, @runpriority INT = 0, @emailoperatorname nvarchar(100) = NULL, @retryattempts INT = NULL, @retrydelay INT = 0, @command nvarchar(4000)= NULL, @loghistcompletionlevel INT = 2, @emailcompletionlevel INT = 0, @description nvarchar(255) = NULL, @tagadditionalinfo nvarchar(96) = NULL, @tagobjectid INT = NULL, @tagobjecttype INT = NULL, @cmdexecsuccesscode INT = 0, @category_name sysname = NULL, -- New for 7.0 @failure_detection BIT = 0, @agent_id INT = NULL, @job_id BINARY(16) = NULL OUTPUT AS BEGIN DECLARE @retval INT declare @step_id int declare @step_name nvarchar(100) declare @step_command nvarchar(1024) declare @on_fail_action tinyint declare @on_success_action tinyint declare @schedule_name nvarchar(100) declare @comments nvarchar(100) SET NOCOUNT ON SELECT @retval = 1 -- 0 means success, 1 means failure set @step_id = 1 set @on_fail_action = 2 -- Return failure set @on_success_action = 1 -- Return success set @step_command = NULL /* ** Set default retries to every minute for 10 minutes. ** */ if @retryattempts = NULL and @retrydelay = 0 begin select @retryattempts = 10 select @retrydelay = 1 end BEGIN TRANSACTION save tran sp_MSadd_repl_job -- Drop the job if it already exists IF EXISTS (SELECT * FROM msdb..sysjobs_view WHERE name = @name collate database_default) begin exec @retval = msdb.dbo.sp_delete_job @job_name=@name if @@ERROR<>0 or @retval<>0 goto UNDO end -- Add the job EXECUTE @retval = msdb.dbo.sp_add_job @job_name = @name, @enabled = @enabled, @start_step_id = 1, @description = @description, @category_name = @category_name, @notify_level_eventlog = @loghistcompletionlevel, @notify_level_email = @emailcompletionlevel, @notify_email_operator_name = @emailoperatorname, @job_id = @job_id OUTPUT IF (@retval <> 0) BEGIN GOTO UNDO END -- Add startup message step if @failure_detection = 1 begin select @step_name = case UPPER(@subsystem collate SQL_Latin1_General_CP1_CS_AS) when N'SNAPSHOT' then formatmessage(21410) when N'LOGREADER' then formatmessage(20528) when N'DISTRIBUTION' then formatmessage(21411) when N'MERGE' then formatmessage(21412) when N'QUEUEREADER' then formatmessage(21422) end select @comments = formatmessage(20529) -- Construct command based on subsystem type select @step_command = case UPPER(@subsystem collate SQL_Latin1_General_CP1_CS_AS) WHEN 'SNAPSHOT' THEN N'sp_MSadd_snapshot_history @perfmon_increment = 0, @agent_id = ' + convert (nvarchar(10), @agent_id) + N', @runstatus = 1, @comments = ''' + @comments + '''' WHEN 'LOGREADER' THEN N'sp_MSadd_logreader_history @perfmon_increment = 0, @agent_id = ' + convert (nvarchar(10), @agent_id) + N', @runstatus = 1, @comments = ''' + @comments + '''' WHEN 'DISTRIBUTION' THEN N'sp_MSadd_distribution_history @perfmon_increment = 0, @agent_id = ' + convert (nvarchar(10), @agent_id) + N', @runstatus = 1, @comments = ''' + @comments + '''' WHEN 'MERGE' THEN N'sp_MSadd_merge_history @perfmon_increment = 0, @agent_id = ' + convert (nvarchar(10),@agent_id) + N', @runstatus = 1, @comments = ''' + @comments + '''' WHEN 'QUEUEREADER' THEN N'sp_MSadd_qreader_history @perfmon_increment = 0, @agent_id = ' + convert (nvarchar(10), @agent_id) + N', @runstatus = 1, @comments = ''' + @comments + '''' end -- Add the job step EXECUTE @retval = msdb.dbo.sp_add_jobstep_internal @job_id = @job_id, @step_id = @step_id, @step_name = @step_name, @command = @step_command, @cmdexec_success_code = @cmdexecsuccesscode, @on_success_action = 3, -- Goto next step @on_fail_action = 3, -- Goto next step @server = @server, @database_name = @databasename, @database_user_name = @username, @os_run_priority = @runpriority IF (@retval <> 0) BEGIN GOTO UNDO END set @step_id = @step_id + 1 set @on_fail_action = 3 -- Goto next step end -- Add the job step select @step_name = formatmessage(20530) EXECUTE @retval = msdb.dbo.sp_add_jobstep_internal @job_id = @job_id, @step_id = @step_id, @step_name = @step_name, @subsystem = @subsystem, @command = @command, @cmdexec_success_code = @cmdexecsuccesscode, @on_success_action = @on_success_action, @on_fail_action = @on_fail_action, @server = @server, @database_name = @databasename, @database_user_name = @username, @retry_attempts = @retryattempts, @retry_interval = @retrydelay, @os_run_priority = @runpriority IF (@retval <> 0) BEGIN GOTO UNDO END -- Add failure message step if @failure_detection = 1 begin set @step_id = @step_id + 1 select @step_name = formatmessage(20531) -- Construct command select @step_command = N'sp_MSdetect_nonlogged_shutdown @subsystem = ''' + @subsystem + N''', @agent_id = ' + convert (nvarchar(10), @agent_id) -- Add the job step EXECUTE @retval = msdb.dbo.sp_add_jobstep_internal @job_id = @job_id, @step_id = @step_id, @step_name = @step_name, @command = @step_command, @cmdexec_success_code = @cmdexecsuccesscode, @on_success_action = 2, -- Always quit with failure @server = @server, @database_name = @databasename, @database_user_name = @username, @os_run_priority = @runpriority IF (@retval <> 0) BEGIN GOTO UNDO END end -- Add the job schedule IF (@activestartdate = 0) SELECT @activestartdate = NULL IF (@activeenddate = 0) SELECT @activeenddate = NULL -- But if @activeenddate is NOT NULL, then @activestartdate cannot be allowed to be NULL either. Set it to today's date converted to the int format used yyyymmdd IF (@activeenddate IS NOT NULL AND @activestartdate IS NULL) SELECT @activestartdate=DATEPART(YYYY,getdate()) * 10000 + DATEPART(MM,getdate()) * 100 + DATEPART(DD,getdate()) -- But never let startdate be > end date IF (@activestartdate > @activeenddate) SELECT @activestartdate=@activeenddate IF (@activestarttimeofday = 0) SELECT @activestarttimeofday = NULL IF (@activeendtimeofday = 0) SELECT @activeendtimeofday = NULL IF (@freqtype <> 0x2) -- OnDemand tasks simply have no schedule in 7.0 BEGIN select @schedule_name = formatmessage(20532) EXECUTE @retval = msdb.dbo.sp_add_jobschedule @job_id = @job_id, @name = @schedule_name, @enabled = 1, @freq_type = @freqtype, @freq_interval = @freqinterval, @freq_subday_type = @freqsubtype, @freq_subday_interval = @freqsubinterval, @freq_relative_interval = @freqrelativeinterval, @freq_recurrence_factor = @freqrecurrencefactor, @active_start_date = @activestartdate, @active_end_date = @activeenddate, @active_start_time = @activestarttimeofday, @active_end_time = @activeendtimeofday IF (@retval <> 0) BEGIN GOTO UNDO END END -- And finally, add the job server EXECUTE @retval = msdb.dbo.sp_add_jobserver @job_id = @job_id, @server_name = '(local)' IF (@retval <> 0) BEGIN GOTO UNDO END COMMIT TRANSACTION -- If this is an autostart LogReader or Distribution or Merge job, add the [new] '-Continuous' paramter to the command IF (@freqtype = 0x40) AND ((UPPER(@subsystem collate SQL_Latin1_General_CP1_CS_AS) = 'LOGREADER') OR (UPPER(@subsystem collate SQL_Latin1_General_CP1_CS_AS) = 'DISTRIBUTION') OR (UPPER(@subsystem collate SQL_Latin1_General_CP1_CS_AS) = 'MERGE') OR (UPPER(@subsystem collate SQL_Latin1_General_CP1_CS_AS) = 'QUEUEREADER')) BEGIN UPDATE msdb.dbo.sysjobsteps SET command = command + ' -Continuous' WHERE (job_id = @job_id) AND ((@failure_detection = 0 and step_id = 1) or (@failure_detection = 1 and step_id = 2)) END -- If this is an autostart job, start it now (for backwards compatibility with 6.x SQLExecutive behaviour) IF (@freqtype = 0x40) EXECUTE msdb.dbo.sp_start_job @job_id = @job_id, @error_flag = 0 RETURN(0) UNDO: rollback tran sp_MSadd_repl_job commit tran return(1) END go raiserror('Creating procedure sp_MScheck_subscription', 0,1) go CREATE PROCEDURE sp_MScheck_subscription ( @publication sysname, -- 1 Tran, 2 Merge @pub_type int )AS declare @merge_pubid uniqueidentifier declare @tran_pubid int declare @retcode int -- Security check exec @retcode = dbo.sp_MSreplcheck_pull @publication = @publication if @retcode <> 0 or @@error <> 0 return 1 if @pub_type = 2 BEGIN if not exists (select * from sysobjects where name = 'sysmergepublications') begin raiserror(20054, 16, -1) return (1) end select @merge_pubid = pubid from sysmergepublications where name=@publication and publisher=@@SERVERNAME and publisher_db=db_name() if @merge_pubid is NULL begin raiserror(20026, 16, -1, @publication) return (1) end if EXISTS (select * from sysmergesubscriptions where pubid=@merge_pubid and subid<>pubid) select 1 else select 0 END else -- if not merge, it has to be tran level. For other level, a generic error will be returned BEGIN if not exists (select * from sysobjects where name='syspublications') begin raiserror(20054, 16, -1) return (1) end select @tran_pubid = pubid from syspublications where name=@publication if @tran_pubid is NULL begin raiserror(20026, 16, -1, @publication) return (1) end if EXISTS (select * from syssubscriptions where (srvid <> -1) and artid in (select artid from sysextendedarticlesview where pubid=@tran_pubid)) select 1 else select 0 END GO exec dbo.sp_MS_marksystemobject sp_MScheck_subscription go grant execute on dbo.sp_MScheck_subscription to public go -- system procedure : returns string representing path to shared tools directory for -- the current instance as an output parm; if unable to get path, returns 1 raiserror(15339,-1,-1,'sp_MSgettools_path') GO CREATE PROCEDURE dbo.sp_MSgettools_path ( @install_path NVARCHAR(260) OUTPUT ) AS BEGIN DECLARE @retcode INTEGER DECLARE @regkey NVARCHAR(260) DECLARE @len_minorversion tinyint SET NOCOUNT ON SELECT @len_minorversion = 1 -- assume only 10's digit of minor version is significant SELECT @regkey = 'SOFTWARE\Microsoft\Microsoft SQL Server\' + dbo.fn_MSsharedversion(@len_minorversion) + '\Tools\ClientSetup' EXECUTE @retcode = master.dbo.xp_regread 'HKEY_LOCAL_MACHINE', @regkey, 'SQLPath', @param = @install_path OUTPUT IF ( @retcode <> 0 ) or ( @@ERROR <> 0 ) or ( @install_path IS NULL ) or ( @install_path = '' ) BEGIN RETURN (1) END RETURN (0) END GO raiserror('Creating procedure sp_replicationoption', 0,1) go CREATE PROCEDURE sp_replicationoption ( @optname sysname, @value nvarchar(5), @security_mode int = 0, @login sysname = 'sa', @password sysname = NULL, @reserved nvarchar(20) = NULL ) AS DECLARE @optbit bit DECLARE @osql_path nvarchar(260) DECLARE @osql_cmd1 nvarchar (255) DECLARE @osql_cmd_full nvarchar (255) DECLARE @osql_for_nt int DECLARE @install_path nvarchar (255) DECLARE @retcode int DECLARE @undo_install nvarchar(20) DECLARE @no_scripts nvarchar(10) DECLARE @platform_nt binary SELECT @platform_nt = 0x1 if is_srvrolemember('sysadmin') <> 1 BEGIN RAISERROR (15232, 14, -1) RETURN (1) END SELECT @no_scripts = 'no_scripts' SELECT @undo_install = 'undo_install' IF db_name() <> 'master' BEGIN RAISERROR(5001, 16,-1) GOTO FAILURE END IF LOWER(@optname collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('transactional','merge') BEGIN RAISERROR(21014, 16, -1) GOTO FAILURE END IF LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('true','false') BEGIN RAISERROR(14137,16,-1) GOTO FAILURE END IF LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) = 'true' SELECT @optbit = 1 ELSE SELECT @optbit = 0 /* ** Check if the option is set as required already */ IF @reserved <> @undo_install AND EXISTS (SELECT * FROM MSreplication_options WHERE optname = @optname AND value = @optbit) BEGIN IF LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) = 'true' RAISERROR (21015, 10, -1, @optname) ELSE RAISERROR (21016, 10, -1, @optname) GOTO FAILURE END /* Install replication */ IF @optbit = 1 BEGIN IF LOWER(@reserved collate SQL_Latin1_General_CP1_CS_AS) = @no_scripts GOTO NO_SCRIPTS -- Set the flag for platform IF (( platform() & @platform_nt = @platform_nt )) SELECT @osql_for_nt = 1 ELSE SELECT @osql_for_nt = 0 /* ** Get installation path -- osql client (TOOLS) path */ EXECUTE @retcode = master.dbo.sp_MSgettools_path @osql_path OUTPUT IF ( @@ERROR <> 0 ) OR ( @retcode <> 0 ) or ( @osql_path is NULL ) or ( @osql_path = '' ) BEGIN GOTO FAILURE END /* ** Get installation path -- instance specific (INSTALL) directory */ exec @retcode = master.dbo.sp_MSget_setup_paths @sql_path = @install_path output IF @@ERROR<> 0 OR @retcode <> 0 or @install_path is NULL or @install_path='' BEGIN GOTO FAILURE END /* ** Install replcom.sql and repltran.sql */ IF @security_mode = 1 begin SELECT @osql_cmd1 = '"' + fn_escapecmdshellsymbolsremovequotes(@osql_path) collate database_default + '\binn\osql" -E ' if serverproperty('instancename') is not null SELECT @osql_cmd1 = @osql_cmd1 + ' -S"' + fn_escapecmdshellsymbols(@@SERVERNAME) collate database_default + '" ' end ELSE -- cannot specify -S w/ -E for local execution, SID does not map SELECT @osql_cmd1 = '"' + fn_escapecmdshellsymbolsremovequotes(@osql_path) collate database_default + '\binn\osql" -U"' + fn_escapecmdshellsymbols(@login) collate database_default + '" -P"' + fn_escapecmdshellsymbols(isnull(@password,'')) collate database_default + '" -S"' + fn_escapecmdshellsymbols(@@SERVERNAME) collate database_default + '" ' select @osql_cmd1 = @osql_cmd1 + '-l30 -t30 ' -- Install replcom.sql -- Only apply replcom.sql if it was not applied before. -- '-b' option will make osql stop at errors and return error code -- We must use this option. IF NOT EXISTS (SELECT * FROM MSreplication_options WHERE value = 1) BEGIN -- Initialize the Command IF (@osql_for_nt = 1) SELECT @osql_cmd_full = '" ' ELSE SELECT @osql_cmd_full = ' ' SELECT @osql_cmd_full = @osql_cmd_full + @osql_cmd1 + ' -dmaster' + ' -b ' + ' -i' + '"' + fn_escapecmdshellsymbolsremovequotes(@install_path) collate database_default + '\install\replcom.sql"' + ' -o' + '"' + fn_escapecmdshellsymbolsremovequotes(@install_path) collate database_default + '\install\replcom.out"' IF (@osql_for_nt = 1) SELECT @osql_cmd_full = @osql_cmd_full + ' "' EXEC @retcode = master..xp_cmdshell @osql_cmd_full IF @@ERROR<> 0 OR @retcode <> 0 BEGIN RAISERROR (14113, 16, -1, @osql_cmd_full, 'replcom.out') GOTO UNDO_INSTALL END END IF LOWER(@optname collate SQL_Latin1_General_CP1_CS_AS) = 'transactional' BEGIN -- Install repltran.sql IF (@osql_for_nt = 1) SELECT @osql_cmd_full = '" ' ELSE SELECT @osql_cmd_full = ' ' SELECT @osql_cmd_full = @osql_cmd_full + @osql_cmd1 + ' -dmaster' + ' -b ' + ' -i' + '"' + fn_escapecmdshellsymbolsremovequotes(@install_path) collate database_default + '\install\repltran.sql"' + ' -o' + '"' + fn_escapecmdshellsymbolsremovequotes(@install_path) collate database_default + '\install\repltran.out"' IF (@osql_for_nt = 1) SELECT @osql_cmd_full = @osql_cmd_full + ' "' EXEC @retcode = master..xp_cmdshell @osql_cmd_full IF @@ERROR<> 0 OR @retcode <> 0 BEGIN RAISERROR (14113, 16, -1, @osql_cmd_full, 'repltran.out') GOTO UNDO_INSTALL END END IF LOWER(@optname collate SQL_Latin1_General_CP1_CS_AS) = 'merge' BEGIN -- Install replmerg.sql IF (@osql_for_nt = 1) SELECT @osql_cmd_full = '" ' ELSE SELECT @osql_cmd_full = ' ' SELECT @osql_cmd_full = @osql_cmd_full + @osql_cmd1 + ' -dmaster' + ' -b ' + ' -i' + '"' + fn_escapecmdshellsymbolsremovequotes(@install_path) collate database_default + '\install\replmerg.sql"' + ' -o' + '"' + fn_escapecmdshellsymbolsremovequotes(@install_path) collate database_default + '\install\replmerg.out"' IF (@osql_for_nt = 1) SELECT @osql_cmd_full = @osql_cmd_full + ' "' EXEC @retcode = master..xp_cmdshell @osql_cmd_full IF @@ERROR<> 0 OR @retcode <> 0 BEGIN RAISERROR (14113, 16, -1, @osql_cmd_full, 'replmerg.out') GOTO UNDO_INSTALL END END NO_SCRIPTS: UPDATE MSreplication_options SET value = @optbit WHERE optname = @optname IF @@ERROR <> 0 BEGIN GOTO UNDO_INSTALL END END /* Uninstall replication */ ELSE BEGIN /* ** Make sure no distributor installed before dropping ** replication stored procedures */ IF EXISTS (SELECT * FROM master..sysservers WHERE srvstatus & 8 <> 0) BEGIN RAISERROR (21021, 16, -1) RETURN(1) END UPDATE MSreplication_options SET value = @optbit WHERE optname = @optname IF @@ERROR <> 0 BEGIN GOTO FAILURE END /* *********** Do not drop replication stored procs anymore. IF LOWER(@optname collate SQL_Latin1_General_CP1_CS_AS) = 'transactional' BEGIN if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSdrop_repltran') begin exec @retcode = dbo.sp_MSdrop_repltran if @@ERROR = 0 and @retcode = 0 drop procedure sp_MSdrop_repltran end END IF LOWER(@optname collate SQL_Latin1_General_CP1_CS_AS) = 'merge' BEGIN if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSdrop_replmerg') begin exec @retcode = dbo.sp_MSdrop_replmerg if @@ERROR = 0 and @retcode = 0 drop procedure sp_MSdrop_replmerg end END IF NOT EXISTS (SELECT * FROM MSreplication_options WHERE value = 1) BEGIN if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSdrop_replcom') begin exec @retcode = dbo.sp_MSdrop_replcom if @@ERROR = 0 and @retcode = 0 drop procedure sp_MSdrop_replcom end END */ END RETURN(0) UNDO_INSTALL: /* This is needed to drop the stored procedures that were created. */ EXEC dbo.sp_replicationoption @optname = @optname, @value = 'false', @reserved = @undo_install FAILURE: RETURN(1) GO exec dbo.sp_MS_marksystemobject sp_replicationoption go grant execute on dbo.sp_replicationoption to public raiserror('Creating procedure sp_helpreplicationoption', 0,1) go CREATE PROCEDURE sp_helpreplicationoption ( @optname sysname = NULL ) AS DECLARE @optbit bit DECLARE @retcode int IF @optname IS NOT NULL AND LOWER(@optname collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('transactional','merge') BEGIN RAISERROR(21014, 16, -1) GOTO FAILURE END SELECT optname, value, major_version, minor_version, revision FROM master..MSreplication_options WHERE optname = @optname OR @optname = NULL RETURN(0) FAILURE: RETURN(1) GO exec dbo.sp_MS_marksystemobject sp_helpreplicationoption go grant execute on dbo.sp_helpreplicationoption to public raiserror('Creating procedure sp_MSgetreplnick', 0,1) GO create procedure sp_MSgetreplnick ( @server sysname = NULL, @db_name sysname = NULL, @pubid uniqueidentifier = NULL, @nickname int output ) as declare @srvid int if @db_name IS NULL select @db_name = db_name() /* Use 0 if the Server name is not passed in since it would be the local server */ if @server IS NULL select @srvid = 0 else select @srvid = max(srvid) from master..sysservers where UPPER(srvname) = UPPER(@server) collate database_default if (@pubid IS NOT NULL) begin select @nickname = max(replnickname) from MSmerge_replinfo where repid in (select subid from sysmergesubscriptions where srvid = @srvid and db_name = @db_name and pubid = @pubid) end else begin select @nickname = max(replnickname) from MSmerge_replinfo where repid in (select subid from sysmergesubscriptions where srvid = @srvid and db_name = @db_name) end go exec dbo.sp_MS_marksystemobject sp_MSgetreplnick go grant execute on dbo.sp_MSgetreplnick to public raiserror('Creating procedure sp_MSreplcheck_publish', 0,1) go CREATE PROCEDURE sp_MSreplcheck_publish AS BEGIN -- -- reintroducing the sysadmin check as it is 4 times more efficient -- than is_member call and reduces performance overhead in case -- the user has sysadmin privileges -- if (is_srvrolemember('sysadmin') = 1 or is_member('db_owner') = 1) return 0 else BEGIN RAISERROR (21050, 14, -1) RETURN (1) END END GO raiserror('Creating procedure sp_MSlocktable', 0,1) go CREATE PROCEDURE sp_MSlocktable @ownername sysname, @tablename sysname AS declare @retcode int declare @procname sysname declare @objid int declare @qualified_name nvarchar(270) select @qualified_name = QUOTENAME(@ownername) + '.' + QUOTENAME(@tablename) select @objid = object_id(@qualified_name) if @objid is NULL select @objid = id from sysobjects where name=@tablename if @objid is null return (1) exec @retcode = dbo.sp_MSrepl_PAL_rolecheck @objid = @objid if (@retcode <> 0 or @@error <> 0) return 1 select @procname = select_proc from sysmergearticles where objid = @objid and select_proc is not NULL exec @retcode = @procname @type = 7 IF @@ERROR<>0 or @retcode<>0 RETURN (1) -- exec ('select count(*) from ' + @ownername + '.' + @tablename + ' (tablock holdlock) where 1 = 2') go exec dbo.sp_MS_marksystemobject sp_MSlocktable go grant execute on dbo.sp_MSlocktable to public go raiserror('Creating procedure sp_MSenumcolumns', 0,1) go CREATE PROCEDURE sp_MSenumcolumns @pubid uniqueidentifier, @artid uniqueidentifier AS declare @retcode int declare @procname sysname select @procname = select_proc from sysmergearticles where pubid = @pubid and artid = @artid exec @retcode = @procname @type =6 go exec dbo.sp_MS_marksystemobject sp_MSenumcolumns go grant execute on dbo.sp_MSenumcolumns to public go /* ** Get pubid through connection_ID and check permission of this publication */ raiserror('Creating procedure sp_MSsetaccesslist', 0,1) go CREATE PROCEDURE sp_MSsetaccesslist @publication sysname, @publisher sysname, @publisher_db sysname AS -- we don't need to do anything here since we are using role based security return 0 go exec dbo.sp_MS_marksystemobject sp_MSsetaccesslist go grant execute on dbo.sp_MSsetaccesslist to public go -- -- Name: sp_MSreplcheck_pull -- -- Description: This proc is called publication PAL security check -- -- Parameter: Refer to the comments in the create procedure statement -- -- Returns: 1 or 0 0 = success -- -- Security: Public procedure -- raiserror('Creating procedure sp_MSreplcheck_pull', 0,1) go create procedure sp_MSreplcheck_pull ( @publication sysname, @raise_fatal_error bit = 1, @pubid uniqueidentifier = NULL, @given_login sysname = NULL ) as begin declare @login sysname ,@login_time datetime -- -- initialize -- if (@given_login = N'') select @given_login = null -- -- Special processing if explicit login was not provided -- if @given_login is null begin -- -- explict login not provided -- sysadmin or db_owner have access -- if (is_srvrolemember('sysadmin') = 1 or is_member('db_owner') = 1) return (0) -- -- If spid with publication in the cache, return success. -- select @login_time = login_time from master..sysprocesses where spid = @@spid if exists (select login_time from tempdb.dbo.MSpublisher_access where spid = @@spid and login_time = @login_time and db_id = db_id() and publication = @publication) return (0) end -- -- Get the current login -- NOTE: why is user_name() not being used -- select @login = suser_sname(suser_sid()) -- -- Special processing if explicit login was provided -- if ((@given_login is not null) and (@login <> @given_login)) begin -- -- To determine whether another login has access to a publication -- requires user to be db_owner in the publishing database -- if is_member('db_owner') <> 1 return (1) select @login = @given_login end -- -- If we have reached here - means - need to get the publication access -- information from distribution db -- declare @has_access bit ,@distribdb sysname ,@distproc nvarchar (300) ,@retcode int ,@dist_rpcname sysname ,@database sysname -- -- initialize RPC information -- select @database = db_name() EXEC @retcode = dbo.sp_helpdistributor @rpcsrvname = @dist_rpcname OUTPUT, @distribdb = @distribdb OUTPUT IF @retcode <> 0 or @@error <> 0 BEGIN RAISERROR (14071, 16, -1) return (1) END IF @retcode <> 0 OR @distribdb IS NULL OR @dist_rpcname IS NULL BEGIN RAISERROR (14071, 16, -1) return(1) END -- -- Invoke call on distribution db -- SELECT @distproc = RTRIM(@dist_rpcname) + '.' + RTRIM(@distribdb) + '.dbo.sp_MSpublication_access' EXEC @retcode = @distproc @publisher = @@SERVERNAME, @publisher_db = @database, @publication = @publication, @operation = 'check', @login = @login, @has_access = @has_access output IF @@error <> 0 OR @retcode <> 0 return (1) -- -- Check access information -- if @has_access = 0 begin -- We don't have access if we reach here, return error IF @raise_fatal_error = 1 RAISERROR (21049, 14, -1, @login, @publication) ELSE RAISERROR (21049, 10, -1, @login, @publication) return(1) end -- -- If explicit login is being used - do not cache -- if (@given_login is not null) return (0) -- -- If we are here - means - need to add access information to the cache. -- Clear the cache to keep it small. -- exec @retcode = dbo.sp_MSflush_access_cache if @retcode <> 0 or @@error <> 0 return (1) -- -- insert entry for this publication access -- insert tempdb.dbo.MSpublisher_access (spid, db_id, publication, login_time, pubid) values (@@spid, db_id(), @publication, @login_time, @pubid) if @@error <> 0 return (1) -- -- all done -- return (0) end GO exec dbo.sp_MS_marksystemobject sp_MSreplcheck_pull go grant execute on dbo.sp_MSreplcheck_pull to public go raiserror('Creating procedure sp_MSreplcheck_connection', 0,1) go CREATE PROCEDURE sp_MSreplcheck_connection @publication sysname = NULL, @artid uniqueidentifier = NULL, @repid uniqueidentifier = NULL, @pubid uniqueidentifier = NULL, @objid int = NULL, @tablenick int = NULL, @is_init bit = 0 AS -- sysadmin or db_owner have access if is_member('db_owner') = 1 return 0 declare @retcode int declare @cached_id uniqueidentifier -- Need login_time to uniquely identify a connection. declare @login_time datetime select @login_time = login_time from master..sysprocesses where spid = @@spid select @cached_id = pubid from tempdb.dbo.MSpublisher_access where spid = @@spid and login_time = @login_time -- If spid with publication in the cache, return success. if @cached_id is null begin -- This stored procedure might be called by common sprocs at -- both the publisher and the subscriber by the merge agent -- The merge agent will call this sp with @is_init = 1 before -- any other calls to the publisher. All the other calls will -- set @is_init to 0. -- it is not a problem if the entry is not found in the cache and -- is_init is set to 0. We should not fail here and instead call -- replcheck_pull to make get the cache entry back. exec @retcode = dbo.sp_MSreplcheck_pull @publication = @publication, @pubid = @pubid if @retcode <> 0 or @@error <> 0 begin return (1) end end else begin if @pubid is not null begin if @pubid <> @cached_id begin RAISERROR (14126, 11, -1) return (1) end end else if @tablenick is not null begin if not exists (select * from sysmergearticles where pubid = @cached_id and nickname = @tablenick) begin RAISERROR (14126, 11, -1) return (1) end end else if @artid is not null begin if not exists (select * from sysmergearticles where pubid = @cached_id and artid = @artid) begin RAISERROR (14126, 11, -1) return (1) end end else if @objid is not null begin if not exists (select * from sysmergearticles where pubid = @cached_id and objid=@objid) begin RAISERROR (14126, 11, -1) return (1) end end else if @publication is not null begin if not exists (select * from sysmergepublications where pubid = @cached_id and name = @publication) begin RAISERROR (14126, 11, -1) return (1) end end else if @repid is not null begin if not exists (select * from sysmergesubscriptions where pubid = @cached_id and subid = @repid) begin RAISERROR (14126, 11, -1) return (1) end end end GO exec dbo.sp_MS_marksystemobject sp_MSreplcheck_connection go grant execute on dbo.sp_MSreplcheck_connection to public go raiserror('Creating procedure sp_MSrepl_PAL_rolecheck', 0,1) go CREATE PROCEDURE sp_MSrepl_PAL_rolecheck @publication sysname = NULL, @artid uniqueidentifier = NULL, @repid uniqueidentifier = NULL, @pubid uniqueidentifier = NULL, @objid int = NULL, @tablenick int = NULL AS -- sysadmin or db_owner have access if is_member('db_owner') = 1 return 0 if (@pubid is not NULL) begin if (1 <> {fn ISPALUSER(@pubid)}) begin RAISERROR (14126, 11, -1) return (1) end end else if (@publication is not NULL) begin if not exists (select * from dbo.sysmergepublications where name = @publication and (1 = {fn ISPALUSER(pubid)})) begin RAISERROR (14126, 11, -1) return (1) end end else if (@artid is not NULL) begin if not exists (select * from dbo.sysmergearticles where artid = @artid and (1 = {fn ISPALUSER(pubid)})) begin RAISERROR (14126, 11, -1) return (1) end end else if (@repid is not NULL) begin if not exists (select * from dbo.sysmergesubscriptions where subid = @repid and (1 = {fn ISPALUSER(pubid)})) begin RAISERROR (14126, 11, -1) return (1) end end else if ((@tablenick is not NULL) and (@tablenick <> 0)) begin if not exists (select * from dbo.sysmergearticles where nickname = @tablenick and (1 = {fn ISPALUSER(pubid)})) begin RAISERROR (14126, 11, -1) return (1) end end else if (@objid is not NULL) begin if not exists (select * from dbo.sysmergearticles where objid = @objid and (1 = {fn ISPALUSER(pubid)})) begin RAISERROR (14126, 11, -1) return (1) end end else if not exists(select * from dbo.sysmergepublications where (1 = {fn ISPALUSER(pubid)})) begin RAISERROR (14126, 11, -1) return (1) end return 0 GO exec dbo.sp_MS_marksystemobject sp_MSrepl_PAL_rolecheck go grant execute on dbo.sp_MSrepl_PAL_rolecheck to public go raiserror('Creating procedure sp_MSreplcheck_qv', 0, 1) GO create procedure sp_MSreplcheck_qv as begin set nocount on declare @qv_replication varchar(10) declare @qv_engine varchar(10) declare @qv_value_replication integer declare @qv_value_engine integer select @qv_replication = '2745196162', @qv_engine = '845129433' exec @qv_value_replication = master.dbo.sp_MSinstance_qv @qv_replication if @@ERROR <> 0 select @qv_value_replication = 1 exec @qv_value_engine = master.dbo.sp_MSinstance_qv @qv_engine if @@ERROR <> 0 select @qv_value_engine = 1 -- magic number 1 assumes least common setting on all failure states select isnull( @qv_value_replication, 1 ) as VALUE_REPLICATION, isnull( @qv_value_engine, 1 ) as VALUE_ENGINE end go exec dbo.sp_MS_marksystemobject sp_MSreplcheck_qv go grant execute on dbo.sp_MSreplcheck_qv to public go raiserror('Creating procedure sp_reinitmergepullsubscription', 0, 1) GO create procedure sp_reinitmergepullsubscription @publisher sysname = 'all', @publisher_db sysname = 'all', @publication sysname = 'all', @upload_first nvarchar(5) = 'FALSE' AS declare @schemaversion int declare @schematype smallint declare @schemaguid uniqueidentifier declare @pubname sysname declare @publisher_name sysname declare @retcode int declare @pubdb sysname declare @pubid uniqueidentifier declare @subid uniqueidentifier declare @artid uniqueidentifier /* ** Security check - Need to be a dbo to call this proc */ exec @retcode = dbo.sp_MSreplcheck_subscribe if @@error<>0 or @retcode<>0 return (1) /* ** Replace 'all' with '%' */ set nocount on if LOWER(@publication) = 'all' SELECT @publication = '%' if LOWER(@publisher) = 'all' SELECT @publisher = '%' if LOWER(@publisher_db) = 'all' SELECT @publisher_db = '%' select @retcode = 0 /* ** At subscriber side, we need to qualify the publication with server name and database name */ IF NOT EXISTS (SELECT * FROM sysmergepublications WHERE name LIKE @publication and ((@publisher = N'%') or (UPPER(publisher) = UPPER(@publisher))) and ((@publisher_db = N'%') or (publisher_db = @publisher_db)) ) BEGIN IF @publication = '%' RAISERROR (14008, 11, -1) ELSE RAISERROR (20026, 11, -1, @publication) RETURN (1) END if LOWER(@upload_first collate SQL_Latin1_General_CP1_CS_AS) not in ('true', 'false') begin raiserror(14148, 16, -1, '@upload_first') return (1) end Declare SYN_CUR CURSOR LOCAL FAST_FORWARD FOR select subs.subid, pubs.name, pubs.publisher, pubs.publisher_db from sysmergepublications pubs, sysmergesubscriptions subs where pubs.name LIKE @publication AND ((@publisher = '%') OR (UPPER(pubs.publisher) = UPPER(@publisher))) AND ((@publisher_db = N'%') OR (pubs.publisher_db = @publisher_db)) AND pubs.pubid=subs.pubid AND subs.pubid<>subs.subid FOR READ ONLY open SYN_CUR fetch SYN_CUR into @subid, @pubname, @publisher_name, @pubdb while (@@fetch_status<>-1) BEGIN -- do not update schemaversion if the initial snapshot has never been applied. update MSmerge_replinfo set schemaversion=-1, recgen = NULL, recguid=NULL, sentgen=NULL, sentguid = NULL where repid=@subid and schemaversion is not null if (@@rowcount <> 0) begin if LOWER(@upload_first collate SQL_Latin1_General_CP1_CS_AS)='true' update sysmergesubscriptions set status=5 where subid=@subid else exec @retcode=sp_MSCleanupForPullReinit @publication=@pubname, @publisher=@publisher_name, @publisher_db=@pubdb if @retcode<>0 or @@ERROR<>0 begin return (1) end end fetch next from SYN_CUR into @subid, @pubname, @publisher_name, @pubdb -- so that it won't be treated as a new susbscription END close SYN_CUR deallocate SYN_CUR -- Forget that publisher ever sent us any generations. They must be resent. -- Publication cleanup will remove the genhistory rows. if @publication = '%' -- get them all update MSmerge_replinfo set recgen = NULL, recguid=NULL, sentgen=NULL, sentguid = NULL else begin select @pubid = pubid from sysmergepublications where name = @publication update MSmerge_replinfo set recgen = NULL, recguid=NULL, sentgen=NULL, sentguid = NULL where repid in (select subid from sysmergesubscriptions where pubid = @pubid) end GO exec dbo.sp_MS_marksystemobject sp_reinitmergepullsubscription go grant execute on dbo.sp_reinitmergepullsubscription to public go raiserror('Creating procedure sp_MSreplcheck_subscribe', 0,1) go CREATE PROCEDURE sp_MSreplcheck_subscribe AS BEGIN -- -- reintroducing the sysadmin check as it is 4 times more efficient -- than is_member call and reduces performance overhead in case -- the user has sysadmin privileges -- if (is_srvrolemember('sysadmin') = 1 or is_member('db_owner') = 1) return 0 else BEGIN RAISERROR (21050, 14, -1) RETURN (1) END END GO raiserror('Creating procedure sp_MSreplicationcompatlevel', 0,1) GO create procedure sp_MSreplicationcompatlevel @dbname sysname, @cmptlevel float(8) As declare @is_distdb smallint select @is_distdb = 0 IF EXISTS (select * from msdb..sysobjects where name='MSdistributiondbs') begin IF EXISTS (SELECT * FROM msdb..MSdistributiondbs where name=@dbname) select @is_distdb = 1 end /* ** Parameter check ** @dbname */ IF NOT EXISTS (SELECT * FROM master.dbo.sysdatabases WHERE name = @dbname collate database_default) BEGIN RAISERROR(15010, 16, -1, @dbname) RETURN(2) END select @dbname = QUOTENAME(@dbname) /* ** Parameter check. NOTE ** @cmptlevel */ IF @cmptlevel<6.0 BEGIN RAISERROR(20060,16,-1) RETURN(2) END /* ** If cmptlevel is lower than 7.0, special attention should be paid. ** If current database is a distribution database or is involed in merge ** replication, then it can not be set to a level lower than 7.0. */ create table #tmp (any_merge smallint NOT NULL) insert into #tmp exec ('select count(*) from ' + @dbname + '..sysobjects where name=' + '''sysmergesubscriptions''' ) if (exists(select any_merge from #tmp where any_merge>0) OR @is_distdb = 1) AND (@cmptlevel<7.0) begin drop table #tmp return 1 end else begin drop table #tmp return 0 end go exec dbo.sp_MS_marksystemobject sp_MSreplicationcompatlevel go raiserror('Creating procedure sp_MShelp_identity_property', 0,1) GO create procedure sp_MShelp_identity_property @tablename sysname, @ownername sysname = NULL AS declare @qualified_name nvarchar(270) declare @objid int declare @retcode int declare @proc nvarchar(300) declare @distributor sysname declare @distribdb sysname declare @publisher sysname declare @publisherdb sysname declare @pub_range bigint declare @sub_range bigint declare @threshold int declare @artid int declare @next_seed bigint declare @current_max bigint declare @replicated_already bit declare @auto_identity_support int declare @identity_incr int declare @current_identity bigint declare @max_identity bigint declare @xprec int declare @xtype int declare @republishing bit declare @length int select @replicated_already = 0 select @auto_identity_support = NULL select @republishing = 0 select @pub_range = NULL select @sub_range = NULL select @threshold = NULL select @next_seed = NULL select @current_max = NULL if @ownername is not NULL begin select @qualified_name = QUOTENAME(@ownername) + '.' + QUOTENAME(@tablename) select @objid = object_id(@qualified_name) end else begin select @qualified_name = QUOTENAME(@tablename) select @objid = id from sysobjects where name=@tablename end if @objid is NULL begin raiserror(14027, 16, -1, @tablename) return (1) end if OBJECTPROPERTY(@objid, 'tablehasidentity') <> 1 begin raiserror(21194, 16, -1) return (1) end select @xtype=xtype, @xprec=xprec, @length=length from syscolumns where id=@objid and columnproperty(id, name, 'IsIdentity')=1 select @max_identity = case @xtype when 52 then power((convert(bigint,2)), 8*2 -1) - 1 --smallint when 48 then power((convert(bigint,2)), 8 - 1) - 1 --tinyint when 56 then power((convert(bigint,2)), 8*4 - 1) - 1 --int when 127 then power((convert(bigint,2)), 62) -1 + power((convert(bigint,2)), 62) --bigint else power((convert(bigint,2)), 62) - 1 + power((convert(bigint,2)), 62) --bigint;. end if (@xtype=108 or @xtype=106) and @xprec<18 select @max_identity = power((convert(bigint,10)), (@xprec+1)) - 1 select @identity_incr = IDENT_INCR(@qualified_name) select @current_identity = ident_current(@qualified_name) if exists (select * from sysobjects where name='sysmergearticles') begin if exists (select * from sysmergearticles where objid=@objid) begin select @replicated_already = 1 select @auto_identity_support = identity_support from sysmergearticles where objid=@objid if not exists (select * from sysmergearticles where objid=@objid and pubid in (select pubid from sysmergepublications where publisher_db=db_name() and LOWER(publisher)=LOWER(@@SERVERNAME))) select @republishing = 1 end end if exists (select * from sysobjects where name='sysarticles') begin if exists (select * from sysarticles where objid=@objid) begin select @replicated_already = 1 select @artid = artid from sysarticles where objid=@objid select @auto_identity_support = identity_support from sysarticleupdates where artid=@artid end end if @auto_identity_support is NOT NULL and @auto_identity_support=1 begin if @republishing = 0 begin select @pub_range = 0 select @sub_range = 0 select @threshold = 0 select @next_seed = 0 select @current_max = 0 select @publisher=@@SERVERNAME select @publisherdb=db_name() EXEC @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT, @distribdb = @distribdb OUTPUT IF @@error <> 0 OR @retcode <> 0 RETURN (1) IF @distribdb is null BEGIN RAISERROR (14071, 16, -1) RETURN (1) END SELECT @proc = RTRIM(@distributor) + '.' + RTRIM(@distribdb) + '.dbo.sp_MScheck_pub_identity' exec @retcode = @proc @publisher=@publisher, @publisher_db=@publisherdb, @tablename=@tablename, @current_max=@current_max OUTPUT, @pub_range=@pub_range OUTPUT, @range = @sub_range OUTPUT, @threshold=@threshold OUTPUT, @next_seed = @next_seed OUTPUT if @retcode<>0 or @@ERROR<>0 return (1) -- Tran pub range is not stored at the distributor if @pub_range = 0 begin if object_id('MSpub_identity_range') is not null begin select @pub_range = pub_range from MSpub_identity_range where objid = @objid end end end else begin select @next_seed=next_seed, @max_identity=max_identity, @pub_range=(max_identity-next_seed)*2/10, @sub_range=(max_identity-next_seed)/10, @threshold=80 from MSrepl_identity_range where objid=@objid end end SELECT 'replicated' = @replicated_already, 'auto_identity_support' = @auto_identity_support, 'identity_incremental' = @identity_incr, 'current_identity' = @current_identity, 'next_starting_seed' = @next_seed, 'max_identity' = @max_identity, 'publisher_range' = ABS(@pub_range), 'subscriber_range' = ABS(@sub_range), 'threshold' = @threshold, 'in_repulishing' = @republishing GO exec dbo.sp_MS_marksystemobject sp_MShelp_identity_property go grant execute on dbo.sp_MShelp_identity_property to public GO raiserror('Creating procedure sp_MSgenreplnickname', 0,1) GO create procedure sp_MSgenreplnickname @srcguid uniqueidentifier, /* Source Guid */ @repnick int output /* nickname */ as declare @binguid binary(16) declare @nickname int set @binguid = convert(binary(16), @srcguid) select @nickname = convert(int, convert(binary(4),substring( convert(nchar(8),@binguid), 1, 2))) while exists (select replnickname from MSmerge_replinfo where replnickname = @nickname) or (@nickname > 0 and @nickname <= 256) begin select @nickname = @nickname + 1 end select @repnick = @nickname go exec dbo.sp_MS_marksystemobject sp_MSgenreplnickname go grant execute on dbo.sp_MSgenreplnickname to public raiserror('Creating procedure sp_MSmergesubscribedb', 0,1) GO CREATE PROCEDURE sp_MSmergesubscribedb( @value sysname ) AS SET NOCOUNT ON /* ** Declarations. */ declare @retcode int /* ** Security Check */ EXEC @retcode = dbo.sp_MSreplcheck_subscribe IF @@ERROR <> 0 or @retcode <> 0 RETURN(1) /* ** Initialization */ /* ** Parameter check ** @value */ IF LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('true','false') BEGIN RAISERROR(14137,16,-1) RETURN(1) END IF LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) = 'true' BEGIN execute @retcode = dbo.sp_MScreate_mergesystables if @@ERROR <> 0 or @retcode <> 0 begin return (1) end END -- We assume we will do nothing about disabling a subscriber GO exec dbo.sp_MS_marksystemobject sp_MSmergesubscribedb go grant execute on dbo.sp_MSmergesubscribedb to public go raiserror('Creating procedure sp_MSenumallsubscriptions', 0,1) go CREATE PROCEDURE sp_MSenumallsubscriptions( @subscription_type nvarchar(5) = 'push', @subscriber_db sysname='%' )AS set nocount on declare @current_db sysname declare @retcode int declare @proc nvarchar(200) declare @db_status int create table #MSenumallsubscriptions ( publisher sysname collate database_default not null, publisher_db sysname collate database_default not null, publication sysname collate database_default null, replication_type int not NULL, subscription_type int not NULL, last_updated datetime null, subscriber_db sysname collate database_default not null, update_mode smallint null, last_sync_status int null, last_sync_summary sysname collate database_default null, last_sync_time datetime null ) declare #cur_db cursor local FAST_FORWARD FOR select DISTINCT name, status FROM master.dbo.sysdatabases where ((@subscriber_db = N'%' collate database_default) or (name = @subscriber_db collate database_default)) and has_dbaccess(name) = 1 open #cur_db fetch #cur_db into @current_db, @db_status while (@@fetch_status <> -1) begin /* * we only return subscriptions in db which is not in loading (0x20), suspect(0x100), * offline(0x200), in recovering(0x80), shutdown(0x40000), not recovered(0x40) */ if (@db_status & 0x403e0) = 0 begin select @proc = QUOTENAME(@current_db) + '.' + 'dbo.sp_MSenumsubscriptions ' insert into #MSenumallsubscriptions exec @retcode = @proc @subscription_type if @@ERROR<>0 or @retcode<>0 begin close #cur_db deallocate #cur_db return (1) end end fetch next from #cur_db into @current_db, @db_status end select distinct 'publisher' = publisher, 'publishing database' = publisher_db, 'publication' = publication, 'replication type' = replication_type, 'subscription type' = subscription_type, 'last updating time' = convert(nvarchar(12), last_updated, 112) + substring(convert(nvarchar(24), last_updated, 121), 11,13), 'subscribing database' = subscriber_db, 'update_mode' = update_mode, 'last sync status' = last_sync_status, 'last sync summary' = last_sync_summary, 'last sync time' = convert(nvarchar(12), last_sync_time, 112) + substring(convert(nvarchar(24), last_sync_time, 121), 11,13) from #MSenumallsubscriptions --drop table #MSenumallsubscriptions close #cur_db deallocate #cur_db return (0) Go grant execute on dbo.sp_MSenumallsubscriptions to public go exec dbo.sp_MS_marksystemobject sp_MSenumallsubscriptions GO raiserror('Creating procedure sp_MSenumsubscriptions', 0,1) go CREATE PROCEDURE sp_MSenumsubscriptions( @subscription_type nvarchar(5) = 'push', @publisher sysname = '%', @publisher_db sysname = '%' )AS set nocount on declare @dbname sysname declare @category int declare @proc nvarchar(200) declare @retcode int declare @cur_db sysname declare @type_value int select @type_value = 100 if LOWER(@subscription_type collate SQL_Latin1_General_CP1_CS_AS)='push' select @type_value = 0 else if LOWER(@subscription_type collate SQL_Latin1_General_CP1_CS_AS)='pull' select @type_value = 1 else if LOWER(@subscription_type collate SQL_Latin1_General_CP1_CS_AS)='both' select @type_value = 2 select @cur_db = db_name() create table #MSenumpushsubscriptions ( publisher sysname collate database_default not null, publisher_db sysname collate database_default not null, publication sysname collate database_default null, replication_type int not NULL, subscription_type int not NULL, last_updated datetime null, subscriber_db sysname collate database_default not null, update_mode smallint null, last_sync_status int null, last_sync_summary sysname collate database_default null, last_sync_time datetime null ) if exists (select * from sysobjects where name='sysmergesubscriptions') begin -- return all subscriptions that this database is a subscriber to -- suppress all subscriptions that originate from this database. insert into #MSenumpushsubscriptions select p.publisher, p.publisher_db, p.name, 2, s.subscription_type, s.last_sync_date, s.db_name, NULL, s.last_sync_status, s.last_sync_summary, s.last_sync_date from sysmergepublications p, sysmergesubscriptions s where p.pubid = s.pubid and (s.subscription_type=@type_value OR @type_value=2) and s.pubid <> s.subid and ((@publisher = N'%') or (p.publisher = @publisher)) and ((@publisher_db = N'%') or ( p.publisher_db = @publisher_db)) and s.db_name = @cur_db and p.pubid not in (select pubid from sysmergepublications pubs where lower(pubs.publisher) = LOWER(@@servername) AND pubs.publisher_db = @cur_db) end if exists (select * from sysobjects where name='MSreplication_subscriptions') begin if exists (select * from sysobjects where name='MSsubscription_properties') and exists (select * from sysobjects where name='MSsubscription_agents ') begin -- update_mode in MSreplication_subscriptions table is not reliable. insert into #MSenumpushsubscriptions select s.publisher, s.publisher_db, s.publication, case isnull(p.publication_type,0) when 0 then 0 else 1 end, s.subscription_type, s.time, @cur_db, -- NOTE: For Queued case: we will always return 2/3 for the 4/5 case -- since we overload update_mode based on queue_type case when isnull(a.update_mode,0) = 4 then 2 when isnull(a.update_mode,0) = 5 then 3 else isnull(a.update_mode,0) end, a.last_sync_status, a.last_sync_summary, a.last_sync_time from MSreplication_subscriptions s with (NOLOCK) left outer join MSsubscription_agents a with (NOLOCK) on (UPPER(s.publisher) = UPPER(a.publisher) and s.publisher_db = a.publisher_db and ((s.publication = a.publication and s.independent_agent = 1 and a.publication <> N'ALL') or (a.publication = N'ALL' and s.independent_agent = 0)) and s.subscription_type = a.subscription_type) left outer join MSsubscription_properties p with (NOLOCK) on (UPPER(s.publisher) = UPPER(p.publisher) and s.publisher_db = p.publisher_db and s.publication = p.publication and -- don't use property table for push. s.subscription_type <> 0) where ((@publisher = N'%') OR (UPPER(s.publisher) = UPPER(@publisher))) AND ((@publisher_db = N'%') or ( s.publisher_db = @publisher_db)) and ((s.subscription_type = 0 and @type_value = 0) or -- For pull, return both pull and anonymous (s.subscription_type <> 0 and @type_value = 1) or @type_value = 2) end -- Property table does not exists. else if exists (select * from sysobjects where name='MSsubscription_agents ') begin -- update_mode in MSreplication_subscriptions table is not reliable. insert into #MSenumpushsubscriptions select s.publisher, s.publisher_db, s.publication, -- Property table does not exists. Say transactional. 0, s.subscription_type, s.time, @cur_db, -- NOTE: For Queued case: we will always return 2/3 for the 4/5 case -- since we overload update_mode based on queue_type case when isnull(a.update_mode,0) = 4 then 2 when isnull(a.update_mode,0) = 5 then 3 else isnull(a.update_mode,0) end, a.last_sync_status, a.last_sync_summary, a.last_sync_time from MSreplication_subscriptions s with (NOLOCK) left outer join MSsubscription_agents a with (NOLOCK) on (UPPER(s.publisher) = UPPER(a.publisher) and s.publisher_db = a.publisher_db and ((s.publication = a.publication and s.independent_agent = 1 and a.publication <> N'ALL') or (a.publication = N'ALL' and s.independent_agent = 0)) and s.subscription_type = a.subscription_type) where ((@publisher = N'%') OR (UPPER(s.publisher) = UPPER(@publisher))) AND ((@publisher_db = N'%') or ( s.publisher_db = @publisher_db)) and ((s.subscription_type = 0 and @type_value = 0) or -- For pull, return both pull and anonymous (s.subscription_type <> 0 and @type_value = 1) or @type_value = 2) end -- Agents table does not exists. else if exists (select * from sysobjects where name='MSsubscription_properties ') begin -- update_mode in MSreplication_subscriptions table is not reliable. insert into #MSenumpushsubscriptions select s.publisher, s.publisher_db, s.publication, case isnull(p.publication_type,0) when 0 then 0 else 1 end, s.subscription_type, s.time, @cur_db, s.update_mode, NULL, --a.last_sync_status, NULL, --a.last_sync_summary, NULL --a.last_sync_time from MSreplication_subscriptions s with (NOLOCK) left outer join MSsubscription_properties p with (NOLOCK) on (UPPER(s.publisher) = UPPER(p.publisher) and s.publisher_db = p.publisher_db and s.publication = p.publication and -- don't use property table for push. s.subscription_type <> 0) where ((@publisher = N'%') OR (UPPER(s.publisher) = UPPER(@publisher))) AND ((@publisher_db = N'%') or ( s.publisher_db = @publisher_db)) and ((s.subscription_type = 0 and @type_value = 0) or -- For pull, return both pull and anonymous (s.subscription_type <> 0 and @type_value = 1) or @type_value = 2) end -- Both table does not exists else begin -- update_mode in MSreplication_subscriptions table is not reliable. insert into #MSenumpushsubscriptions select s.publisher, s.publisher_db, s.publication, 0, s.subscription_type, s.time, @cur_db, s.update_mode, NULL, -- a.last_sync_status, NULL, -- a.last_sync_summary NULL -- a.last_sync_time from MSreplication_subscriptions s with (NOLOCK) where ((@publisher = N'%') OR (UPPER(s.publisher) = UPPER(@publisher))) AND ((@publisher_db = N'%') or ( s.publisher_db = @publisher_db)) and ((s.subscription_type = 0 and @type_value = 0) or -- For pull, return both pull and anonymous (s.subscription_type <> 0 and @type_value = 1) or @type_value = 2) end end select * from #MSenumpushsubscriptions --drop table #MSenumpushsubscriptions return (0) GO grant execute on dbo.sp_MSenumsubscriptions to public go exec dbo.sp_MS_marksystemobject sp_MSenumsubscriptions GO raiserror('Creating procedure sp_MSenumallpublications', 0,1) go CREATE PROCEDURE sp_MSenumallpublications( @publisherdb sysname = '%', @replication_type tinyint = null, -- by default return all types of publication @agent_login sysname = NULL, @security_check bit = 1, -- Security check by default so that things depending on security -- filtering will not break immediately @vendor_name sysname = NULL, -- Use vender name to filter the result of third party publications. @publication sysname = NULL ) as BEGIN set nocount on declare @dbname sysname declare @trans tinyint declare @merge tinyint declare @3rdparty tinyint declare @retcode int DECLARE @dist_rpcname sysname declare @distribdb sysname declare @login sysname declare @proc nvarchar(255) declare @distbit int declare @is_user_admin bit declare @same_as_user bit -- UI: If the distributor is not installed, return empty result if not exists (SELECT * FROM master.dbo.sysservers WHERE srvstatus & 8 <> 0) return (0) -- UI: Win95 subscriber will send in null agent_login -- Assume the agent login to be the current login if it is NT login if @security_check = 1 and @agent_login is null and not exists (select * from master.dbo.syslogins where sid = suser_sid() and isntname = 0) select @agent_login = suser_sname(suser_sid()) /* Initializations */ select @trans = 1 select @merge = 2 select @3rdparty = 0 select @login = suser_sname(suser_sid()) SELECT @distbit = 16 select @is_user_admin = 0 select @same_as_user = 0 -- Get publication list create table #pubdbs (publisher_db sysname collate database_default not null, replication_type int NOT NULL) create table #MSenumpublications (publisher_db sysname collate database_default not null, publication sysname collate database_default not null, replication_type tinyint NOT NULL, immediate_sync bit NOT NULL, allow_pull bit NOT NULL, allow_anonymous bit NOT NULL, enabled_for_internet bit NOT NULL, repl_freq tinyint NOT NULL, immediate_sync_ready bit NOT NULL, allow_sync_tran bit NOT NULL, independent_agent bit NOT NULL, is_db_owner int NOT NULL, thirdparty_flag bit NOT NULL, vendor_name sysname collate database_default null, publisher sysname collate database_default null, description nvarchar(255) collate database_default null, distribution_db sysname collate database_default null, allow_queued_tran bit not null, allow_dts bit not null, thirdparty_options int null, queue_type int null, dynamic_filters bit not null default 0) create table #admin_publications (publisher_db sysname collate database_default not null, publication sysname collate database_default not null) create table #agent_publications (publisher_db sysname collate database_default not null, publication sysname collate database_default not null) /* Return everything if @replication_type is not in (@3rdparty, @trans, @merge) */ if not @replication_type in (@3rdparty, @trans, @merge) select @replication_type = null if @replication_type = @trans or @replication_type is null insert into #pubdbs select name, @trans from master.dbo.sysdatabases where ((@publisherdb = N'%') or ( name = @publisherdb collate database_default)) and category & 1 <> 0 and has_dbaccess(name) = 1 if @replication_type = @merge or @replication_type is null insert into #pubdbs select name, @merge from master.dbo.sysdatabases where ((@publisherdb = N'%') or ( name = @publisherdb collate database_default)) and category & 4 <> 0 and has_dbaccess(name) = 1 if @replication_type = @3rdparty insert into #pubdbs select name, @3rdparty from master.dbo.sysdatabases where ((@publisherdb = N'%') or ( name = @publisherdb collate database_default)) and category & @distbit <> 0 and has_dbaccess(name) = 1 declare hCForEachDb CURSOR LOCAL FAST_FORWARD FOR select publisher_db, replication_type from #pubdbs FOR READ ONLY open hCForEachDb fetch hCForEachDb into @dbname, @replication_type /* Loop for each database */ while (@@fetch_status >= 0) begin if (@replication_type) = @trans select @proc = quotename(@dbname) + '.dbo.sp_MSenumtranpublications' else if (@replication_type) = @merge select @proc = quotename(@dbname) + '.dbo.sp_MSenummergepublications' else if (@replication_type) = @3rdparty select @proc = quotename(@dbname) + '.dbo.sp_MSenum3rdpartypublications' if (@replication_type) = @3rdparty insert into #MSenumpublications exec @retcode = @proc @vendor_name, @publication else insert into #MSenumpublications exec @retcode = @proc @publication if @@ERROR <> 0 or @retcode <> 0 return (1) fetch hCForEachDb into @dbname, @replication_type end /* while FETCH_SUCCESS */ -- Prepare for filtering. IF EXISTS (SELECT * FROM msdb.dbo.sysobjects WHERE name = 'MSdistpublishers' and xtype = 'U') -- this is the distributor, check if publisher too if not exists (select * from msdb.dbo.MSdistpublishers where upper(name) = upper(@@SERVERNAME) collate database_default) -- not publisher select @security_check = 0 -- no need to go through security check for none-publisher -- since it won't have any publication other than third party ones. IF (@security_check <> 0) BEGIN EXEC @retcode = dbo.sp_helpdistributor @rpcsrvname = @dist_rpcname OUTPUT, @distribdb = @distribdb OUTPUT IF @@error <> 0 OR @retcode <> 0 RETURN (1) IF @distribdb is null BEGIN RAISERROR (14071, 16, -1) RETURN (1) END SELECT @proc = RTRIM(@dist_rpcname) + '.' + RTRIM(@distribdb) + '.dbo.sp_MSpublication_access' -- Optimization if is_srvrolemember('sysadmin') = 1 select @is_user_admin = 1 else insert into #admin_publications EXEC @retcode = @proc @publisher = @@SERVERNAME, @operation = 'get_publications', @login = @login if suser_sid(@agent_login) = suser_sid() select @same_as_user = 1 else insert into #agent_publications EXEC @retcode = @proc @publisher = @@SERVERNAME, @operation = 'get_publications', @login = @agent_login END -- IF (@security_check <> 0) -- commit open tran in case -- insert into exec failed. while(@@trancount <> 0) commit tran select pub.publisher_db, pub.publication, pub.replication_type, pub.immediate_sync, pub.allow_pull, pub.allow_anonymous, pub.enabled_for_internet, pub.repl_freq, pub.immediate_sync_ready, pub.allow_sync_tran, pub.independent_agent, N'agent_access' = case when (@same_as_user = 1 or exists (select * from #agent_publications agent where agent.publisher_db = pub.publisher_db and agent.publication = pub.publication)) then convert(bit,1) else convert(bit,0) end, pub.thirdparty_flag, pub.vendor_name, pub.publisher, pub.description, pub.distribution_db, allow_queued_tran, allow_dts, pub.thirdparty_options, pub.queue_type, pub.dynamic_filters from #MSenumpublications pub where exists (select * from #admin_publications admin where pub.publisher_db = admin.publisher_db and pub.publication = admin.publication) or @security_check = 0 or pub.is_db_owner = 1 or @is_user_admin = 1 order by pub.publication, pub.publisher_db return (0) END go grant execute on dbo.sp_MSenumallpublications to public go raiserror('Creating procedure sp_MSenumtranpublications', 0,1) go CREATE PROCEDURE sp_MSenumtranpublications ( @publication sysname ) as BEGIN set nocount on select db_name(), name, 1, immediate_sync, allow_pull, allow_anonymous, enabled_for_internet, repl_freq, immediate_sync_ready, allow_sync_tran, independent_agent, is_member('db_owner'), 0, -- thirdparty 'Microsoft SQL Server', @@servername, description, convert(sysname, null), allow_queued_tran, allow_dts ,convert(int,null) -- thirdparty_options ,queue_type ,0 -- dynamic_filters from syspublications pubs where exists (select * from sysextendedarticlesview art where pubs.pubid = art.pubid) and status <> 0 and (pubs.name = @publication or @publication is null) END go raiserror('Creating procedure sp_MSenummergepublications', 0,1) go CREATE PROCEDURE sp_MSenummergepublications ( @publication sysname ) as BEGIN declare @publisher sysname declare @publisher_db sysname select @publisher=@@SERVERNAME select @publisher_db=db_name() set nocount on select db_name(), name, 2, 1, allow_pull, allow_anonymous, enabled_for_internet, 0, snapshot_ready, 0, 1, is_member('db_owner'), 0, --thirdparty 'Microsoft SQL Server', publisher, description, convert(sysname, null), convert(bit,0), --allow_queued_tran convert(bit,0) --allow_dts ,convert(int, null) -- thirdparty_options ,convert(int, null) -- queue_type ,dynamic_filters from sysmergepublications p where status <> 0 and LOWER(publisher)=LOWER(@publisher) and publisher_db=@publisher_db and (p.name = @publication or @publication is null) END go raiserror('Creating procedure sp_MSenum3rdpartypublications', 0,1) go CREATE PROCEDURE sp_MSenum3rdpartypublications ( @vendor_name sysname, @publication sysname ) as BEGIN set nocount on select pubs.publisher_db, publication, case when publication_type <> 2 then 1 else 2 end, --replication_type, 1 tran, 2 merge ; pub type 0 tran 1 snapshot, 2 merge immediate_sync, allow_pull, allow_anonymous, 0, --enabled_for_internet, case when publication_type = 0 then 0 else 1 end, --repl_freq, 1, --immediate_sync_ready, always return 1 so that UI will not warn 0, -- allow_sync_tran, independent_agent, is_member('db_owner'), 1, --thirdparty pubs.vendor_name, srv.srvname, pubs.description, db_name(), convert(bit,0), --allow_queued_tran convert(bit,0) --allow_dts ,thirdparty_options ,convert(int, null) -- queue_type ,0 -- dynamic_filters from MSpublications pubs, master..sysservers srv where exists (select * from MSarticles art where pubs.publication_id = art.publication_id) and thirdparty_flag <> 0 and publisher_id = srvid and (@vendor_name <> 'others' and vendor_name = @vendor_name or @vendor_name = 'others' and (vendor_name is null or vendor_name = '') or @vendor_name is null ) and (pubs.publication = @publication or @publication is null) END go raiserror('Creating procedure sp_MSenumthirdpartypublicationvendornames', 0,1) go CREATE PROCEDURE sp_MSenumthirdpartypublicationvendornames( @within_db bit = 0 ) as set nocount on if @within_db = 0 begin declare @dbname sysname declare @retcode int declare @distbit int declare @proc nvarchar(300) --init SELECT @distbit = 16 -- Get publication list create table #pubdbs (publisher_db sysname collate database_default not null) insert into #pubdbs select name from master..sysdatabases where category & @distbit <> 0 and has_dbaccess(name) = 1 create table #MSenumpublications (vendor_name sysname collate database_default not null) declare hCForEachDb CURSOR LOCAL FAST_FORWARD FOR select publisher_db from #pubdbs FOR READ ONLY open hCForEachDb fetch hCForEachDb into @dbname /* Loop for each database */ while (@@fetch_status >= 0) begin select @proc = quotename(@dbname) + '.dbo.sp_MSenumthirdpartypublicationvendornames' insert into #MSenumpublications exec @retcode = @proc 1 if @@ERROR <> 0 or @retcode <> 0 return (1) fetch hCForEachDb into @dbname end /* while FETCH_SUCCESS */ end else begin select distinct vendor_name from MSpublications where thirdparty_flag = 1 and vendor_name is not null and vendor_name <> '' end select distinct vendor_name from #MSenumpublications order by vendor_name return (0) go grant execute on dbo.sp_MSenumthirdpartypublicationvendornames to public go dump tran master with no_log GO raiserror('Creating procedure sp_reinitpullsubscription', 0,1) go CREATE PROCEDURE sp_reinitpullsubscription ( @publisher sysname, @publisher_db sysname, @publication sysname = 'all' /* publication name */ )AS SET NOCOUNT ON declare @subscription_type int declare @sync_type tinyint /* ** Security Check */ declare @retcode int EXEC @retcode = dbo.sp_MSreplcheck_subscribe IF @@ERROR <> 0 or @retcode <> 0 RETURN(1) /* ** Initializations. */ /* ** Parameter Check: @publisher ** Check to make sure that the publisher is define */ IF @publisher IS NULL BEGIN RAISERROR (14043, 16, -1, '@publisher') RETURN (1) END IF @publisher = 'all' BEGIN RAISERROR (14136, 16, -1) RETURN (1) END EXECUTE @retcode = dbo.sp_validname @publisher IF @@ERROR <> 0 OR @retcode <> 0 RETURN (1) /* ** Parameter Check: @publisher_db */ IF @publisher_db IS NULL BEGIN RAISERROR (14043, 16, -1, '@publisher_db') RETURN (1) END IF @publisher_db = 'all' BEGIN RAISERROR (14136, 16, -1) RETURN (1) END EXECUTE @retcode = dbo.sp_validname @publisher_db IF @@ERROR <> 0 OR @retcode <> 0 RETURN (1) /* ** Parameter Check: @publication ** */ IF @publication IS NULL BEGIN RAISERROR (14043, 16, -1, '@publication') RETURN (1) END IF LOWER(@publication) = 'all' select @publication = '%' ELSE BEGIN EXECUTE @retcode = dbo.sp_validname @publication IF @@ERROR <> 0 OR @retcode <> 0 RETURN (1) END IF NOT EXISTS (SELECT * FROM MSreplication_subscriptions WHERE UPPER(publisher) = UPPER(@publisher) AND publisher_db = @publisher_db AND publication like @publication ) BEGIN RAISERROR(14135, 11, -1, @publisher, @publisher_db, @publication) RETURN(1) END select @sync_type = immediate_sync from MSreplication_subscriptions WHERE UPPER(publisher) = UPPER(@publisher) AND publisher_db = @publisher_db AND publication like @publication IF @sync_type = 0 BEGIN raiserror(21059, 16, -1) return (1) END UPDATE MSreplication_subscriptions set transaction_timestamp = 0x00 WHERE UPPER(publisher) = UPPER(@publisher) AND publisher_db = @publisher_db AND publication like @publication if @@ERROR<>0 RETURN (1) -- Reset the attach state so that the distribution agent will not adjust attach state. if @publication <> '%' begin select @subscription_type = subscription_type from MSreplication_subscriptions WHERE UPPER(publisher) = UPPER(@publisher) AND publisher_db = @publisher_db AND publication = @publication and -- Don't do this for push subscription_type <> 0 if @subscription_type is not null begin exec @retcode = dbo.sp_MSreset_attach_state @publisher = @publisher, @publisher_db = @publisher_db, @publication = @publication, @subscription_type = @subscription_type if @retcode <> 0 or @@error <> 0 return (1) end end GO grant execute on dbo.sp_reinitpullsubscription to public go raiserror('Creating procedure sp_addpullsubscription', 0,1) go CREATE PROCEDURE sp_addpullsubscription ( @publisher sysname, @publisher_db sysname, @publication sysname, /* publication name */ @independent_agent nvarchar(5) = 'true', /* true or false */ @subscription_type nvarchar(9) = 'anonymous', /* subscription_type, pull or anonymous */ @description nvarchar(100) = NULL, -- SyncTran @update_mode nvarchar(15) = 'read only', -- 'sync tran', 'queued tran', 'failover' @immediate_sync bit = 1 ) AS BEGIN SET NOCOUNT ON /* ** Declarations. */ DECLARE @retcode int DECLARE @subscription_type_id int /* 1 = pull, 2 = anonymous */ DECLARE @independent_agent_id bit -- SyncTran DECLARE @update_mode_id tinyint -- For attach if exists (select * from sysobjects where name = 'MSrepl_restore_stage') begin raiserror(21211, 16, -1) return 1 end /* ** Check if replication components are installed on this server */ exec @retcode = dbo.sp_MS_replication_installed if (@retcode <> 1) begin return (1) end /* ** Security Check */ EXEC @retcode = dbo.sp_MSreplcheck_subscribe IF @@ERROR <> 0 or @retcode <> 0 RETURN(1) /* ** Initializations. */ /* ** Parameter Check: @publisher ** Check to make sure that the publisher is define */ IF @publisher IS NULL BEGIN RAISERROR (14043, 16, -1, '@publisher') RETURN (1) END IF @publisher = 'all' BEGIN RAISERROR (14136, 16, -1) RETURN (1) END EXECUTE @retcode = dbo.sp_validname @publisher IF @@ERROR <> 0 OR @retcode <> 0 RETURN (1) /* ** Parameter Check: @publisher_db */ IF @publisher_db IS NULL BEGIN RAISERROR (14043, 16, -1, '@publisher_db') RETURN (1) END IF @publisher_db = 'all' BEGIN RAISERROR (14136, 16, -1) RETURN (1) END EXECUTE @retcode = dbo.sp_validname @publisher_db IF @@ERROR <> 0 OR @retcode <> 0 RETURN (1) /* ** Parameter Check: @publication ** */ IF @publication IS NULL BEGIN RAISERROR (14043, 16, -1, '@publication') RETURN (1) END IF @publication = 'all' BEGIN RAISERROR (14136, 16, -1) RETURN (1) END EXECUTE @retcode = dbo.sp_validname @publication IF @@ERROR <> 0 OR @retcode <> 0 RETURN (1) IF @independent_agent IS NULL OR LOWER(@independent_agent collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('true', 'false') BEGIN RAISERROR (14148, 16, -1, '@independent_agent') RETURN (1) END IF LOWER(@independent_agent collate SQL_Latin1_General_CP1_CS_AS) = 'true' SELECT @independent_agent_id = 1 ELSE SELECT @independent_agent_id = 0 /* ** Parameter Check: @subscription_type ** The @status value can be: ** ** type_id type ** ====== ======== ** 0 push ** 1 pull ** 2 anonymous ** ** Note: @subscription_type = push is only used by distribution agents */ IF @subscription_type IS NULL OR LOWER(@subscription_type collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('push', 'pull','anonymous') BEGIN RAISERROR (20016, 16, -1) RETURN (1) END IF LOWER(@subscription_type collate SQL_Latin1_General_CP1_CS_AS) = 'pull' SELECT @subscription_type_id = 1 ELSE IF LOWER(@subscription_type collate SQL_Latin1_General_CP1_CS_AS) = 'anonymous' SELECT @subscription_type_id = 2 ELSE SELECT @subscription_type_id = 0 IF @independent_agent_id = 0 AND @subscription_type_id = 2 BEGIN RAISERROR (21026, 16, -1) RETURN (1) END -- SyncTran /* ** Parameter check: @update_mode */ /* ** Parameter check: @update_mode */ IF (@update_mode IS NULL OR LOWER(@update_mode collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('read only', 'sync tran', 'queued tran', 'failover')) BEGIN RAISERROR (20502, 16, -1, '@update_mode') RETURN (1) END -- Anonymous subscriptions should not be allowed to -- subscribe with 'synctran option' IF LOWER(@update_mode collate SQL_Latin1_General_CP1_CS_AS) in ('sync tran', 'queued tran', 'failover') and @subscription_type_id = 2 begin RAISERROR (21057, 16, -1) RETURN (1) end select @update_mode_id = case when LOWER(@update_mode collate SQL_Latin1_General_CP1_CS_AS) = 'sync tran' then 1 when LOWER(@update_mode collate SQL_Latin1_General_CP1_CS_AS) = 'queued tran' then 4 when LOWER(@update_mode collate SQL_Latin1_General_CP1_CS_AS) = 'failover' then 5 else 0 end begin tran save TRAN addpullsubscription /* ** Check to see if MSreplication_subscriptions and MSsubscription_properties ** tables exists. ** If not, create it. */ exec @retcode = dbo.sp_MScreate_sub_tables @tran_sub_table = 1, @property_table = 1 IF @@ERROR <> 0 or @retcode <> 0 goto UNDO /* ** Check to make sure that the subscription does not already exist */ declare @sub_type int select @sub_type = subscription_type from MSreplication_subscriptions WHERE UPPER(publisher) = UPPER(@publisher) AND publisher_db = @publisher_db AND publication = @publication -- It is not allowed to subscribe to the same publication twice even with -- differnet subscription type. -- Raise special error for push if @sub_type is not null if @sub_type = 0 begin raiserror (20594, 16, -1) GOTO UNDO end else begin RAISERROR (14058, 16, -1) GOTO UNDO end /* ** Add the subscription */ INSERT MSreplication_subscriptions (publisher, publisher_db, publication, independent_agent, subscription_type, distribution_agent, description, time, transaction_timestamp, -- SyncTran update_mode, immediate_sync) VALUES (@publisher, @publisher_db, @publication, @independent_agent_id, @subscription_type_id, NULL, @description, getdate(), 0, -- SyncTran @update_mode_id, @immediate_sync ) IF @@ERROR <> 0 BEGIN RAISERROR (14057, 16, -1) GOTO UNDO END COMMIT TRAN RETURN (0) UNDO: IF @@TRANCOUNT > 0 begin ROLLBACK TRAN addpullsubscription COMMIT TRAN end return 1 END go raiserror('Creating procedure sp_MSupdatesharedagentproperties', 0,1) go CREATE PROCEDURE sp_MSupdatesharedagentproperties ( @publisher sysname, @publisher_db sysname, @publication sysname, @property sysname, @strvalue nvarchar(256) = NULL, @intvalue int = NULL, @subscription_type int ) AS -- Note publisher/publisher_db/publication uniquely identifies -- a subscription in MSreplication_subscriptions CREATE TABLE #subscriptions ( publication sysname collate database_default ) -- Compute the list of affected subscriptions INSERT INTO #subscriptions SELECT publication FROM MSreplication_subscriptions WHERE UPPER(publisher) = UPPER(@publisher) AND publisher_db = @publisher_db AND publication <> @publication AND independent_agent = 0 AND subscription_type = @subscription_type IF (SELECT COUNT(*) FROM #subscriptions) > 0 BEGIN IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = N'distributor' BEGIN UPDATE MSsubscription_properties SET distributor = @strvalue WHERE UPPER(publisher) = UPPER(@publisher) AND publisher_db = @publisher_db AND publication in (SELECT publication FROM #subscriptions) END ELSE IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = N'distributor_security_mode' BEGIN UPDATE MSsubscription_properties SET distributor_security_mode = @intvalue WHERE UPPER(publisher) = UPPER(@publisher) AND publisher_db = @publisher_db AND publication in (SELECT publication FROM #subscriptions) END ELSE IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = N'distributor_login' BEGIN UPDATE MSsubscription_properties SET distributor_login = @strvalue WHERE UPPER(publisher) = UPPER(@publisher) AND publisher_db = @publisher_db AND publication in (SELECT publication FROM #subscriptions) END ELSE IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = N'distributor_password' BEGIN UPDATE MSsubscription_properties SET distributor_password = @strvalue WHERE UPPER(publisher) = UPPER(@publisher) AND publisher_db = @publisher_db AND publication in (SELECT publication FROM #subscriptions) END ELSE IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = N'distributor_password' BEGIN UPDATE MSsubscription_properties SET distributor_password = @strvalue WHERE UPPER(publisher) = UPPER(@publisher) AND publisher_db = @publisher_db AND publication in (SELECT publication FROM #subscriptions) END ELSE IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = N'ftp_address' BEGIN UPDATE MSsubscription_properties SET ftp_address = @strvalue WHERE UPPER(publisher) = UPPER(@publisher) AND publisher_db = @publisher_db AND publication in (SELECT publication FROM #subscriptions) END ELSE IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = N'ftp_port' BEGIN UPDATE MSsubscription_properties SET ftp_port = @intvalue WHERE UPPER(publisher) = UPPER(@publisher) AND publisher_db = @publisher_db AND publication in (SELECT publication FROM #subscriptions) END ELSE IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = N'ftp_login' BEGIN UPDATE MSsubscription_properties SET ftp_login = @strvalue WHERE UPPER(publisher) = UPPER(@publisher) AND publisher_db = @publisher_db AND publication in (SELECT publication FROM #subscriptions) END ELSE IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = N'ftp_password' BEGIN UPDATE MSsubscription_properties SET ftp_password = @strvalue WHERE UPPER(publisher) = UPPER(@publisher) AND publisher_db = @publisher_db AND publication in (SELECT publication FROM #subscriptions) END ELSE IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = N'alt_snapshot_folder' BEGIN UPDATE MSsubscription_properties SET alt_snapshot_folder = @strvalue WHERE UPPER(publisher) = UPPER(@publisher) AND publisher_db = @publisher_db AND publication in (SELECT publication FROM #subscriptions) END ELSE IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = N'working_directory' BEGIN UPDATE MSsubscription_properties SET working_directory = @strvalue WHERE UPPER(publisher) = UPPER(@publisher) AND publisher_db = @publisher_db AND publication in (SELECT publication FROM #subscriptions) END ELSE IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = N'use_ftp' BEGIN UPDATE MSsubscription_properties SET use_ftp = @intvalue WHERE UPPER(publisher) = UPPER(@publisher) AND publisher_db = @publisher_db AND publication in (SELECT publication FROM #subscriptions) END ELSE IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = N'offload_agent' BEGIN UPDATE MSsubscription_properties SET offload_agent = @intvalue WHERE UPPER(publisher) = UPPER(@publisher) AND publisher_db = @publisher_db AND publication in (SELECT publication FROM #subscriptions) END ELSE IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = N'offload_server' BEGIN UPDATE MSsubscription_properties SET offload_server = @strvalue WHERE UPPER(publisher) = UPPER(@publisher) AND publisher_db = @publisher_db AND publication in (SELECT publication FROM #subscriptions) END END DROP TABLE #subscriptions IF @@ERROR <> 0 RETURN 1 ELSE RETURN 0 GO /* Create sp_replicationdboption */ raiserror('Creating procedure sp_replicationdboption', 0,1) GO CREATE PROCEDURE sp_replicationdboption ( @dbname sysname, @optname sysname, @value sysname, @ignore_distributor bit = 0, @from_scripting bit = 0 ) AS SET NOCOUNT ON /* ** Declarations. */ declare @alert_name sysname declare @alert_id int declare @command nvarchar(255) declare @description nvarchar(500) declare @category_name sysname declare @agentname sysname DECLARE @retcode int DECLARE @optbit int DECLARE @optbit_value int /* Desired value with the optbit mask */ DECLARE @proc nvarchar(255) , @category int /* ** Initialization */ /* ** Parameter check ** @dbname */ SELECT @category = category FROM master.dbo.sysdatabases WHERE name = @dbname collate database_default if @category is null BEGIN RAISERROR(15010, 16, -1, @dbname) RETURN(1) END /* ** Parameter check ** @type */ IF @optname is null or LOWER(@optname collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('publish', 'merge publish', 'subscribe', -- Used by sp_dboption for backward compatibility only. 'sync with backup', 'max cmds in tran' ) BEGIN RAISERROR(14138,16,-1,@optname) RETURN(1) END /* ** Parameter check ** @value */ IF LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('true','false') BEGIN RAISERROR(14137,16,-1) RETURN(1) END /* ** Security Check */ -- This proc is not granted to public. Only other system proc or sysadmin can use this -- sp_dboption will call this and it has its own security check, /* ** If we're in a transaction, disallow this since it might make recovery ** impossible. ** */ IF @@trancount > 0 BEGIN RAISERROR(15002,16,-1,'sp_replicationdboption') RETURN(1) END IF LOWER(@optname collate SQL_Latin1_General_CP1_CS_AS) = 'publish' BEGIN SELECT @optbit = 1 SELECT @proc = QUOTENAME(@dbname) + '.dbo.sp_MSpublishdb' END ELSE IF LOWER(@optname collate SQL_Latin1_General_CP1_CS_AS) = 'merge publish' BEGIN SELECT @optbit = 4 SELECT @proc = QUOTENAME(@dbname) + '.dbo.sp_MSmergepublishdb' END ELSE IF LOWER(@optname collate SQL_Latin1_General_CP1_CS_AS) = 'subscribe' BEGIN SELECT @optbit = 2 END ELSE IF LOWER(@optname collate SQL_Latin1_General_CP1_CS_AS) = 'sync with backup' BEGIN SELECT @optbit = 32 END ELSE IF LOWER(@optname collate SQL_Latin1_General_CP1_CS_AS) = 'max cmds in tran' BEGIN SELECT @optbit = 64 END IF LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) = 'true' SELECT @optbit_value = @optbit ELSE SELECT @optbit_value = 0 /* ** Check if the option is set as required already */ if (@category & @optbit) = @optbit_value BEGIN if @optbit_value = 64 -- setting 'max cmds in tran' to the same, do nothing RETURN (0) if LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) = 'true' RAISERROR (14035, 10, -1, @optname, @dbname) else RAISERROR (14037, 10, -1, @optname, @dbname) RETURN (1) END -- If turning on 'sync with backup', make sure 'publish' or 'dist' is turned on already. if @optbit_value = 32 and (@category & 1 = 0 and @category & 16 = 0) begin raiserror(20019, 16, -1, 'sync with backup') return (1) end if @optbit_value = 64 and (@category & 16 = 0) begin raiserror(20019, 16, -1, 'max cmds in tran') return (1) end -- We do not allow turning on sync with backup mode at publishing db if the db is -- in simple recovery mode if @optbit_value = 32 and @category & 1 <> 0 and databasepropertyex(@dbname, 'recovery') = 'SIMPLE' begin raiserror(20622, 16, -1, 'sync with backup') return (1) end -- If turning off 'publish', turn off 'sync with backup' as well if the database -- is not a distribution database. if @optbit = 1 and @optbit_value = 0 and @category & 32 <> 0 and @category & 16 = 0 begin EXEC @retcode = dbo.sp_replicationdboption @dbname = @dbname, @optname = 'sync with backup', @value = 'false', @ignore_distributor = @ignore_distributor, @from_scripting = @from_scripting IF @@ERROR <> 0 or @retcode <> 0 BEGIN GOTO UNDO END end -- if turning on 'sync with backup' a distribution database, initialize the backup lsns -- to nulls, this should be done before the category bit is set. declare @backup_proc nvarchar(1000) if @optbit_value = 32 and @category & 16 <> 0 begin SELECT @backup_proc = QUOTENAME(@dbname) + '.dbo.sp_MSrepl_init_backup_lsns' exec @retcode = @backup_proc if @@error <> 0 or @retcode <> 0 goto UNDO end /* ** Prepare the required option */ if @proc is not null begin EXEC @retcode = @proc @value = @value, @ignore_distributor = @ignore_distributor IF @@ERROR <> 0 or @retcode <> 0 BEGIN GOTO UNDO END end /* ** Preparation succeeded. ** Toggle the category bit in master..sysdatabases */ UPDATE master..sysdatabases SET category = category ^ @optbit WHERE name = @dbname IF @@ERROR <> 0 BEGIN GOTO UNDO END declare @num_mergedb int select @num_mergedb = null if lower(@optname collate SQL_Latin1_General_CP1_CS_AS) = 'merge publish' begin if lower(@value collate SQL_Latin1_General_CP1_CS_AS) = 'true' begin -- Set the 'startup' option for sp_MScleanupmergepublisher if the -- database is enabled for merge replication. exec ('use master exec dbo.sp_procoption ''sp_MScleanupmergepublisher'', ''startup'', ''true''') end else begin -- Reset the 'startup' option for sp_MScleanupmergepublisher if -- this is the last database that has its 'merge publish' option -- disabled select @num_mergedb = count(*) from master..sysdatabases where (category & 4) <> 0 if @num_mergedb = 0 begin exec ('use master exec dbo.sp_procoption ''sp_MScleanupmergepublisher'', ''startup'', ''false''') end end end -- Get expired subscription cleanup agent name set @agentname = formatmessage(20569) IF ((LOWER(@optname collate SQL_Latin1_General_CP1_CS_AS) = 'merge publish') or (LOWER(@optname) = 'publish')) and (LOWER(@value) = 'true') BEGIN IF NOT EXISTS (SELECT * FROM msdb..sysjobs_view WHERE name = @agentname collate database_default and UPPER(originating_server) = UPPER(CONVERT(sysname, SERVERPROPERTY('ServerName')))) BEGIN SELECT @command = 'EXEC dbo.sp_expired_subscription_cleanup' set @description = formatmessage(20542) select @category_name = name FROM msdb.dbo.syscategories where category_id = 17 EXECUTE @retcode = msdb.dbo.sp_MSadd_repl_job @agentname, @subsystem = 'TSQL', @server = @@SERVERNAME, @databasename = @dbname, @description = @description, @freqtype = 4, -- daily @activestarttimeofday=010000, -- from 01:00:00 am @command = @command, @enabled = 1, @retryattempts = 0, @loghistcompletionlevel = 0, @category_name = @category_name IF @@ERROR <> 0 or @retcode <> 0 BEGIN return (1) END END -- Expired subscription cleanup alert select @category_name = name FROM msdb.dbo.syscategories where category_id = 20 set @alert_name = formatmessage(20538) set @alert_id = 14157 -- corresponding to formatmessage(20538) if not exists (select * from msdb.dbo.sysalerts where message_id = @alert_id) begin exec @retcode = msdb.dbo.sp_add_alert @enabled = 0, @name = @alert_name, @category_name = @category_name, @message_id = 14157 if @@error <> 0 or @retcode <> 0 goto UNDO end END IF ((LOWER(@optname collate SQL_Latin1_General_CP1_CS_AS) = 'merge publish') or (LOWER(@optname collate SQL_Latin1_General_CP1_CS_AS) = 'publish')) and (LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) = 'false') BEGIN IF (EXISTS (SELECT * FROM msdb..sysjobs_view WHERE name = @agentname collate database_default and UPPER(originating_server) = UPPER(CONVERT(sysname, SERVERPROPERTY('ServerName'))))) and (NOT exists (select name from master..sysdatabases where category & 4 =4 )) and (NOT exists (select name from master..sysdatabases where category & 1 =1)) BEGIN EXEC @retcode = msdb.dbo.sp_delete_job @job_name = @agentname IF @@ERROR <> 0 or @retcode <> 0 return (1) END set @alert_id = 14157 -- cleanup alert set @alert_name = formatmessage(20569) if exists (select * from msdb.dbo.sysalerts where message_id=@alert_id) and (NOT exists (select name from master..sysdatabases where category & 4 =4 )) and (NOT exists (select name from master..sysdatabases where category & 1 =1)) begin select @alert_name=name from msdb.dbo.sysalerts where message_id=@alert_id exec @retcode = msdb.dbo.sp_delete_alert @alert_name if @@error <> 0 or @retcode <> 0 return (1) end END /* ** ??? ** CHECKPOINT the database that was changed. Make the change ** effective immediatly */ CHECKPOINT IF @@ERROR <> 0 BEGIN RETURN(1) END RETURN(0) UNDO: -- Create system table is not allowed in a multi-statement transactions. -- Drop the tables here IF LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) = 'true' EXEC dbo.sp_replicationdboption @dbname = @dbname, @optname = @optname, @value = 'false', @ignore_distributor = @ignore_distributor return(1) GO raiserror('Creating procedure sp_MSfixupdistributorinfo', 0,1) go CREATE PROCEDURE sp_MSfixupdistributorinfo ( @publisher sysname, @publisher_db sysname, @publication sysname, @distributor sysname, @subscription_type int ) AS DECLARE @local_distributor sysname DECLARE @retcode INT -- If @distributor = @publisher -- we just assume that these values are unspecified -- and so we inherit these values from other shared subscriptions -- if possible IF @distributor = @publisher BEGIN SELECT TOP 1 @local_distributor = sp.distributor FROM MSsubscription_properties sp JOIN MSreplication_subscriptions rs ON UPPER(sp.publisher) = UPPER(rs.publisher) AND sp.publisher_db = rs.publisher_db AND rs.subscription_type = @subscription_type AND rs.independent_agent = 0 WHERE UPPER(sp.publisher) = UPPER(@publisher) AND sp.publisher_db = @publisher_db AND sp.publication <> @publication IF @@ROWCOUNT > 0 BEGIN -- Inherit the values from other shared subscriptions UPDATE MSsubscription_properties SET distributor = @local_distributor WHERE UPPER(publisher) = UPPER(@publisher) AND publisher_db = @publisher_db AND publication = @publication END END ELSE BEGIN EXEC @retcode = sp_MSupdatesharedagentproperties @publisher = @publisher, @publisher_db = @publisher_db, @publication = @publication, @property = N'distributor', @strvalue = @distributor, @subscription_type = @subscription_type IF @retcode <> 0 OR @@ERROR <> 0 GOTO FixupFailure END RETURN 0 FixupFailure: RETURN 1 GO raiserror('Creating procedure sp_MSfixupdistributorsecurity', 0,1) go CREATE PROCEDURE sp_MSfixupdistributorsecurity ( @publisher sysname, @publisher_db sysname, @publication sysname, @distributor_security_mode int, -- default 0 -- standard @distributor_login sysname, -- default 'sa' @distributor_password nvarchar(524), -- default null @subscription_type int ) AS DECLARE @local_distributor_security_mode int DECLARE @local_distributor_login sysname DECLARE @local_distributor_password nvarchar(524) DECLARE @retcode INT IF @distributor_security_mode = 0 AND @distributor_login = 'sa' AND (@distributor_password IS NULL OR @distributor_password = N'') BEGIN -- Parameters are unspecifed, try to inherit values from -- shared susbcriptions SELECT TOP 1 @local_distributor_security_mode = distributor_security_mode, @local_distributor_login = distributor_login, @local_distributor_password = distributor_password FROM MSsubscription_properties sp JOIN MSreplication_subscriptions rs ON UPPER(sp.publisher) = UPPER(rs.publisher) AND sp.publisher_db = rs.publisher_db AND rs.subscription_type = @subscription_type AND rs.independent_agent = 0 WHERE UPPER(sp.publisher) = UPPER(@publisher) AND sp.publisher_db = @publisher_db AND sp.publication <> @publication IF @@ROWCOUNT > 0 BEGIN -- Inherit the values from other shared subscriptions UPDATE MSsubscription_properties SET distributor_security_mode = @local_distributor_security_mode, distributor_login = @local_distributor_login, distributor_password = @local_distributor_password WHERE UPPER(publisher) = UPPER(@publisher) AND publisher_db = @publisher_db AND publication = @publication END END ELSE BEGIN EXEC @retcode = sp_MSupdatesharedagentproperties @publisher = @publisher, @publisher_db = @publisher_db, @publication = @publication, @property = N'distributor_security_mode', @intvalue = @distributor_security_mode, @subscription_type = @subscription_type IF @retcode <> 0 OR @@ERROR <> 0 GOTO FixupFailure EXEC @retcode = sp_MSupdatesharedagentproperties @publisher = @publisher, @publisher_db = @publisher_db, @publication = @publication, @property = N'distributor_login', @strvalue = @distributor_login, @subscription_type = @subscription_type IF @retcode <> 0 OR @@ERROR <> 0 GOTO FixupFailure EXEC @retcode = sp_MSupdatesharedagentproperties @publisher = @publisher, @publisher_db = @publisher_db, @publication = @publication, @property = N'distributor_password', @strvalue = @distributor_password, @subscription_type = @subscription_type IF @retcode <> 0 OR @@ERROR <> 0 GOTO FixupFailure END RETURN 0 FixupFailure: RETURN 1 GO raiserror('Creating procedure sp_MSfixupftpinfo', 0,1) go CREATE PROCEDURE sp_MSfixupftpinfo ( @publisher sysname, @publisher_db sysname, @publication sysname, @ftp_address sysname, -- default null @ftp_port int, -- default null @ftp_login sysname, -- default null @ftp_password nvarchar(524), -- default null @subscription_type int, @force_null bit ) AS DECLARE @local_ftp_address sysname DECLARE @local_ftp_port sysname DECLARE @local_ftp_login sysname DECLARE @local_ftp_password nvarchar(524) DECLARE @retcode INT IF @ftp_address IS NULL AND @ftp_port IS NULL AND @ftp_login IS NULL AND @ftp_password IS NULL AND @force_null = 0 BEGIN -- Parameters are unspecifed, try to inherit values from -- shared susbcriptions SELECT TOP 1 @local_ftp_address = ftp_address, @local_ftp_port = ftp_port, @local_ftp_login = ftp_login, @local_ftp_password = ftp_password FROM MSsubscription_properties sp JOIN MSreplication_subscriptions rs ON UPPER(sp.publisher) = UPPER(rs.publisher) AND sp.publisher_db = rs.publisher_db AND rs.subscription_type = @subscription_type AND rs.independent_agent = 0 WHERE UPPER(sp.publisher) = UPPER(@publisher) AND sp.publisher_db = @publisher_db AND sp.publication <> @publication IF @@ROWCOUNT > 0 BEGIN -- Inherit the values from other shared subscriptions UPDATE MSsubscription_properties SET ftp_address = @local_ftp_address, ftp_port = @local_ftp_port, ftp_login = @local_ftp_login, ftp_password = @local_ftp_password WHERE UPPER(publisher) = UPPER(@publisher) AND publisher_db = @publisher_db AND publication = @publication END END ELSE BEGIN EXEC @retcode = sp_MSupdatesharedagentproperties @publisher = @publisher, @publisher_db = @publisher_db, @publication = @publication, @property = N'ftp_address', @strvalue = @ftp_address, @subscription_type = @subscription_type IF @retcode <> 0 OR @@ERROR <> 0 GOTO FixupFailure EXEC @retcode = sp_MSupdatesharedagentproperties @publisher = @publisher, @publisher_db = @publisher_db, @publication = @publication, @property = N'ftp_port', @intvalue = @ftp_port, @subscription_type = @subscription_type IF @retcode <> 0 OR @@ERROR <> 0 GOTO FixupFailure EXEC @retcode = sp_MSupdatesharedagentproperties @publisher = @publisher, @publisher_db = @publisher_db, @publication = @publication, @property = N'ftp_login', @strvalue = @ftp_login, @subscription_type = @subscription_type IF @retcode <> 0 OR @@ERROR <> 0 GOTO FixupFailure EXEC @retcode = sp_MSupdatesharedagentproperties @publisher = @publisher, @publisher_db = @publisher_db, @publication = @publication, @property = N'ftp_password', @strvalue = @ftp_password, @subscription_type = @subscription_type IF @retcode <> 0 OR @@ERROR <> 0 GOTO FixupFailure END RETURN 0 FixupFailure: RETURN 1 GO raiserror('Creating procedure sp_MSfixupaltsnapshotfolder', 0,1) go CREATE PROCEDURE sp_MSfixupaltsnapshotfolder ( @publisher sysname, @publisher_db sysname, @publication sysname, @alt_snapshot_folder nvarchar(255), -- default null @subscription_type int, @force_null bit ) AS DECLARE @local_alt_snapshot_folder sysname DECLARE @retcode INT IF @alt_snapshot_folder IS NULL AND @force_null = 0 BEGIN -- Parameter is unspecifed, try to inherit value from -- shared susbcriptions SELECT TOP 1 @local_alt_snapshot_folder = alt_snapshot_folder FROM MSsubscription_properties sp JOIN MSreplication_subscriptions rs ON UPPER(sp.publisher) = UPPER(rs.publisher) AND sp.publisher_db = rs.publisher_db AND rs.subscription_type = @subscription_type AND rs.independent_agent = 0 WHERE UPPER(sp.publisher) = UPPER(@publisher) AND sp.publisher_db = @publisher_db AND sp.publication <> @publication IF @@ROWCOUNT > 0 BEGIN -- Inherit the values from other shared subscriptions UPDATE MSsubscription_properties SET alt_snapshot_folder = @local_alt_snapshot_folder WHERE UPPER(publisher) = UPPER(@publisher) AND publisher_db = @publisher_db AND publication = @publication END END ELSE BEGIN EXEC @retcode = sp_MSupdatesharedagentproperties @publisher = @publisher, @publisher_db = @publisher_db, @publication = @publication, @property = N'alt_snapshot_folder', @strvalue = @alt_snapshot_folder, @subscription_type = @subscription_type IF @retcode <> 0 OR @@ERROR <> 0 GOTO FixupFailure END RETURN 0 FixupFailure: RETURN 1 GO raiserror('Creating procedure sp_MSfixupworkingdirectory', 0,1) go CREATE PROCEDURE sp_MSfixupworkingdirectory ( @publisher sysname, @publisher_db sysname, @publication sysname, @working_directory nvarchar(255), -- default null @subscription_type int ) AS DECLARE @local_working_directory sysname DECLARE @retcode INT IF @working_directory IS NULL BEGIN -- Parameter is unspecifed, try to inherit value from -- shared susbcriptions SELECT TOP 1 @local_working_directory = working_directory FROM MSsubscription_properties sp JOIN MSreplication_subscriptions rs ON UPPER(sp.publisher) = UPPER(rs.publisher) AND sp.publisher_db = rs.publisher_db AND rs.subscription_type = @subscription_type AND rs.independent_agent = 0 WHERE UPPER(sp.publisher) = UPPER(@publisher) AND sp.publisher_db = @publisher_db AND sp.publication <> @publication IF @@ROWCOUNT > 0 BEGIN -- Inherit the values from other shared subscriptions UPDATE MSsubscription_properties SET working_directory = @local_working_directory WHERE UPPER(publisher) = UPPER(@publisher) AND publisher_db = @publisher_db AND publication = @publication END END ELSE BEGIN EXEC @retcode = sp_MSupdatesharedagentproperties @publisher = @publisher, @publisher_db = @publisher_db, @publication = @publication, @property = N'working_directory', @strvalue = @working_directory, @subscription_type = @subscription_type IF @retcode <> 0 OR @@ERROR <> 0 GOTO FixupFailure END RETURN 0 FixupFailure: RETURN 1 GO raiserror('Creating procedure sp_MSfixupuseftp', 0,1) go CREATE PROCEDURE sp_MSfixupuseftp ( @publisher sysname, @publisher_db sysname, @publication sysname, @use_ftp bit, -- default null @subscription_type int, @force_zero bit ) AS DECLARE @local_use_ftp bit DECLARE @retcode INT IF @use_ftp = 0 AND @force_zero = 0 BEGIN -- Parameter is unspecifed, try to inherit value from -- shared susbcriptions SELECT TOP 1 @local_use_ftp = use_ftp FROM MSsubscription_properties sp JOIN MSreplication_subscriptions rs ON UPPER(sp.publisher) = UPPER(rs.publisher) AND sp.publisher_db = rs.publisher_db AND rs.subscription_type = @subscription_type AND rs.independent_agent = 0 WHERE UPPER(sp.publisher) = UPPER(@publisher) AND sp.publisher_db = @publisher_db AND sp.publication <> @publication IF @@ROWCOUNT > 0 BEGIN -- Inherit the values from other shared subscriptions UPDATE MSsubscription_properties SET use_ftp = @local_use_ftp WHERE UPPER(publisher) = UPPER(@publisher) AND publisher_db = @publisher_db AND publication = @publication END END ELSE BEGIN EXEC @retcode = sp_MSupdatesharedagentproperties @publisher = @publisher, @publisher_db = @publisher_db, @publication = @publication, @property = N'use_ftp', @intvalue = @use_ftp, @subscription_type = @subscription_type IF @retcode <> 0 OR @@ERROR <> 0 GOTO FixupFailure END RETURN 0 FixupFailure: RETURN 1 GO raiserror('Creating procedure sp_MSfixup_offload_agent_info', 0,1) go CREATE PROCEDURE sp_MSfixupagentoffloadinfo ( @publisher sysname, @publisher_db sysname, @publication sysname, @distributor sysname, @offload_agent bit, -- default 0 @offload_server sysname, -- default null @subscription_type int ) AS DECLARE @local_offload_agent bit DECLARE @local_offload_server sysname DECLARE @retcode INT IF @offload_agent = 0 AND @offload_server is null BEGIN -- Parameters are assumed to be be unspecified, try to inherit values -- from shared subscriptions SELECT TOP 1 @local_offload_agent = offload_agent, @local_offload_server = offload_server FROM MSsubscription_properties sp JOIN MSreplication_subscriptions rs ON UPPER(sp.publisher) = UPPER(rs.publisher) AND sp.publisher_db = rs.publisher_db AND rs.subscription_type = @subscription_type AND rs.independent_agent = 0 WHERE UPPER(sp.publisher) = UPPER(@publisher) AND sp.publisher_db = @publisher_db AND sp.publication <> @publication IF @@ROWCOUNT > 0 BEGIN -- Inherit the values from other shared subscriptions UPDATE MSsubscription_properties SET offload_agent = @local_offload_agent, offload_server = @local_offload_server WHERE UPPER(publisher) = UPPER(@publisher) AND publisher_db = @publisher_db AND publication = @publication END END ELSE BEGIN EXEC @retcode = sp_MSupdatesharedagentproperties @publisher = @publisher, @publisher_db = @publisher_db, @publication = @publication, @property = N'offload_agent', @intvalue = @offload_agent, @subscription_type = @subscription_type IF @retcode <> 0 OR @@ERROR <> 0 GOTO FixupFailure EXEC @retcode = sp_MSupdatesharedagentproperties @publisher = @publisher, @publisher_db = @publisher_db, @publication = @publication, @property = N'offload_server', @strvalue = @offload_server, @subscription_type = @subscription_type END RETURN 0 FixupFailure: RETURN 1 GO raiserror('Creating procedure sp_MSfixupsharedagentproperties', 0,1) go CREATE PROCEDURE sp_MSfixupsharedagentproperties ( @publisher sysname, @publisher_db sysname, @publication sysname, /* publication name */ @distributor sysname, -- default @publisher @distributor_security_mode int, -- default 0 -- standard @distributor_login sysname, -- default 'sa' @distributor_password nvarchar(524), -- default null @ftp_address sysname, -- default null @ftp_port int, -- default null @ftp_login sysname, -- default null @ftp_password nvarchar(524), -- default null @alt_snapshot_folder nvarchar(255), -- default null @working_directory nvarchar(255), -- default null @use_ftp bit, -- default 0 @offload_agent bit, -- default 0 @offload_server sysname -- default @distributor ) AS DECLARE @subscription_type int DECLARE @retcode int DECLARE @force_ftp_null bit DECLARE @force_alt_snapshot_folder_null bit IF @alt_snapshot_folder IS NOT NULL AND @alt_snapshot_folder <> N'' SELECT @force_ftp_null = 1 ELSE SELECT @force_ftp_null = 0 IF (@use_ftp = 1) OR (@ftp_address IS NOT NULL AND @ftp_address <> N'') SELECT @force_alt_snapshot_folder_null = 1 ELSE SELECT @force_alt_snapshot_folder_null = 0 SELECT @subscription_type = subscription_type FROM MSreplication_subscriptions WHERE UPPER(publisher) = UPPER(@publisher) AND publisher_db = @publisher_db AND publication = @publication -- No need to fix up the publisher security properties -- because they are defined on a per subscription -- basis for SyncTran EXEC @retcode = sp_MSfixupdistributorinfo @publisher = @publisher, @publisher_db = @publisher_db, @publication = @publication, @distributor = @distributor, @subscription_type = @subscription_type IF @@ERROR <> 0 OR @retcode <> 0 GOTO FixupFailure EXEC @retcode = sp_MSfixupdistributorsecurity @publisher = @publisher, @publisher_db = @publisher_db, @publication = @publication, @distributor_login = @distributor_login, @distributor_password = @distributor_password, @distributor_security_mode = @distributor_security_mode, @subscription_type = @subscription_type IF @@ERROR <> 0 OR @retcode <> 0 GOTO FixupFailure /* Ignore ftp_address, ftp_port, ftp_login, ftp_password on post 7.0 server EXEC @retcode = sp_MSfixupftpinfo @publisher = @publisher, @publisher_db = @publisher_db, @publication = @publication, @ftp_address = @ftp_address, @ftp_port = @ftp_port, @ftp_login = @ftp_login, @ftp_password = @ftp_password, @subscription_type = @subscription_type, @force_null = @force_ftp_null IF @@ERROR <> 0 OR @retcode <> 0 GOTO FixupFailure */ EXEC @retcode = sp_MSfixupaltsnapshotfolder @publisher = @publisher, @publisher_db = @publisher_db, @publication = @publication, @alt_snapshot_folder = @alt_snapshot_folder, @subscription_type = @subscription_type, @force_null = @force_alt_snapshot_folder_null IF @@ERROR <> 0 OR @retcode <> 0 GOTO FixupFailure EXEC @retcode = sp_MSfixupworkingdirectory @publisher = @publisher, @publisher_db = @publisher_db, @publication = @publication, @working_directory = @working_directory, @subscription_type = @subscription_type IF @@ERROR <> 0 OR @retcode <> 0 GOTO FixupFailure EXEC @retcode = sp_MSfixupuseftp @publisher = @publisher, @publisher_db = @publisher_db, @publication = @publication, @use_ftp = @use_ftp, @subscription_type = @subscription_type, @force_zero = @force_ftp_null IF @@ERROR <> 0 OR @retcode <> 0 GOTO FixupFailure EXEC @retcode = sp_MSfixupagentoffloadinfo @publisher = @publisher, @publisher_db = @publisher_db, @publication = @publication, @distributor = @distributor, @offload_agent = @offload_agent, @offload_server = @offload_server, @subscription_type = @subscription_type IF @@ERROR <> 0 OR @retcode <> 0 GOTO FixupFailure RETURN 0 FixupFailure: RETURN 1 GO raiserror('Creating procedure sp_addpullsubscription_agent', 0,1) go CREATE PROCEDURE sp_addpullsubscription_agent ( @publisher sysname, @publisher_db sysname, @publication sysname, /* publication name */ @subscriber sysname = NULL, @subscriber_db sysname = NULL, @subscriber_security_mode int = NULL, /* 0 standard; 1 integrated */ @subscriber_login sysname = NULL, @subscriber_password sysname = NULL, @distributor sysname = @publisher, @distribution_db sysname = NULL, @distributor_security_mode int = 0, @distributor_login sysname = 'sa', @distributor_password sysname = NULL, @optional_command_line nvarchar(4000) = '', @frequency_type int = 2 , /* 2== OnDemand */ @frequency_interval int = 1, @frequency_relative_interval int = 1, @frequency_recurrence_factor int = 1, @frequency_subday int = 1, @frequency_subday_interval int = 1 , @active_start_time_of_day int = 0, @active_end_time_of_day int = 0, @active_start_date int = 0, @active_end_date int =0, @distribution_jobid binary(16) = NULL OUTPUT, @encrypted_distributor_password bit = 0, @enabled_for_syncmgr nvarchar(5) = 'false', /* Enabled for SYNCMGR: true or false */ @ftp_address sysname = NULL, @ftp_port int = NULL, @ftp_login sysname = NULL, @ftp_password sysname = NULL, @alt_snapshot_folder nvarchar(255) = NULL, @working_directory nvarchar(255) = NULL, @use_ftp nvarchar(5) = 'false', @publication_type tinyint = 0,-- 0 - Transactional, 1 - Snapshot, 2 - Merge @dts_package_name sysname = NULL, /* value will be sent and validated at distributor */ @dts_package_password sysname = NULL, @dts_package_location nvarchar(12) = N'subscriber', @reserved nvarchar(100) = N'', -- Not default to null because null problems in conditional expressions. @offloadagent nvarchar(5) = 'false', @offloadserver sysname = NULL, @job_name sysname = NULL ) AS SET NOCOUNT ON /* ** Declarations. */ DECLARE @command nvarchar(4000) DECLARE @retcode int DECLARE @subscription_type_id int /* 1 = pull, 2 = anonymous */ DECLARE @independent_agent_id bit DECLARE @distribution_agent nvarchar(100) DECLARE @category_name sysname DECLARE @platform_nt binary DECLARE @subscriber_enc_password nvarchar(524) DECLARE @distributor_enc_password nvarchar(524) DECLARE @use_ftp_bit bit DECLARE @offload_agent_bit bit select @platform_nt = 0x1 /* ** Security Check */ EXEC @retcode = dbo.sp_MSreplcheck_subscribe IF @@ERROR <> 0 or @retcode <> 0 RETURN(1) /* ** Initializations. */ -- Set null @optional_command_line to empty string to avoid string concat problem if @optional_command_line is null set @optional_command_line = '' else set @optional_command_line = N' ' + LTRIM( RTRIM(@optional_command_line) ) + N' ' IF @distributor_password = N'' select @distributor_password = NULL IF @ftp_password = N'' select @ftp_password = NULL IF @dts_package_password = N'' select @dts_package_password = NULL /* ** Parameter Check: @publisher ** Check to make sure that the publisher is define */ IF @publisher IS NULL BEGIN RAISERROR (14043, 16, -1, '@publisher') RETURN (1) END EXECUTE @retcode = dbo.sp_validname @publisher IF @@ERROR <> 0 OR @retcode <> 0 RETURN (1) /* ** Parameter Check: @publisher_db */ IF @publisher_db IS NULL BEGIN RAISERROR (14043, 16, -1, '@publisher_db') RETURN (1) END EXECUTE @retcode = dbo.sp_validname @publisher_db IF @@ERROR <> 0 OR @retcode <> 0 RETURN (1) /* ** Parameter Check: @publication ** */ IF @publication IS NULL BEGIN RAISERROR (14043, 16, -1, '@publication') RETURN (1) END EXECUTE @retcode = dbo.sp_validname @publication IF @@ERROR <> 0 OR @retcode <> 0 RETURN (1) /* ** Parameter Check: @subscriber and @subscriber_db */ if @subscriber IS NULL or rtrim(@subscriber) = '' SELECT @subscriber = @@SERVERNAME if @subscriber_db IS NULL or rtrim(@subscriber_db) = '' SELECT @subscriber_db = DB_NAME() EXECUTE @retcode = dbo.sp_validname @subscriber IF @@ERROR <> 0 OR @retcode <> 0 RETURN (1) EXECUTE @retcode = dbo.sp_validname @subscriber_db IF @@ERROR <> 0 OR @retcode <> 0 RETURN (1) /* ** Check to see if MSreplictaion_subscriptions table exists. ** If so, copy it into the temp table */ IF NOT EXISTS (SELECT * FROM sysobjects WHERE type = 'U' AND name = 'MSreplication_subscriptions') BEGIN RAISERROR (20017, 16, -1) RETURN (1) END /* ** Check to make sure that the subscription does exist */ IF NOT EXISTS (SELECT * FROM MSreplication_subscriptions WHERE UPPER(publisher) = UPPER(@publisher) AND publisher_db = @publisher_db AND publication = @publication) BEGIN RAISERROR (20017, 16, -1) RETURN (1) END declare @update_mode_id int SELECT @distribution_agent = NULL SELECT @independent_agent_id = independent_agent, @subscription_type_id = subscription_type, @distribution_agent = distribution_agent, @update_mode_id = update_mode FROM MSreplication_subscriptions WHERE UPPER(publisher) = UPPER(@publisher) AND publisher_db = @publisher_db AND publication = @publication /* Distribution agent for push subscriptions is at distributor side */ IF @subscription_type_id = 0 BEGIN RAISERROR (21001, 16, -1) RETURN (1) END IF @distribution_agent IS NOT NULL BEGIN RAISERROR (21002, 11, -1, @distribution_agent) RETURN (1) END -- Parameter check: @subscriber_security_mode if @subscriber_security_mode is null begin if ( platform() & @platform_nt ) = @platform_nt select @subscriber_security_mode = 1 else select @subscriber_security_mode = 0 end if ( ( platform() & @platform_nt ) <> @platform_nt and @subscriber_security_mode = 1 ) begin RAISERROR(21038, 16, -1) RETURN (1) end if (@subscription_type_id <> 0) begin if (@subscriber_security_mode = 0) and (@subscriber_login IS NULL or rtrim(@subscriber_login) = '') begin raiserror(21344, 16, -1, '@subscriber_login') return (1) end end if (@distributor_security_mode = 0) and (@distributor_login IS NULL or rtrim(@distributor_login) = '') begin raiserror(3217, 16, -1, '@distributor_login') return (1) end IF NOT EXISTS (select * from sysobjects where name = 'MSsubscription_properties' and type = 'U') begin exec @retcode = sp_MScreate_sub_tables @property_table = 1 if @retcode <> 0 or @@error <> 0 return (1) end /* ** Parameter check: @alt_snapshot_folder ** @alt_snapshot_folder and @use_ftp are mutually exclusive */ IF @alt_snapshot_folder <> N'' AND @alt_snapshot_folder IS NOT NULL AND LOWER(@use_ftp collate SQL_Latin1_General_CP1_CS_AS) = N'true' BEGIN RAISERROR(21146, 16, -1) RETURN (1) END /* ** Parameter check: @use_ftp ** Must be 'true' or 'false' */ IF LOWER(@use_ftp collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('true', 'false') BEGIN RAISERROR (14148, 16, -1, '@use_ftp') RETURN (1) END IF LOWER(@use_ftp collate SQL_Latin1_General_CP1_CS_AS) = 'true' BEGIN SELECT @use_ftp_bit = 1 END ELSE BEGIN SELECT @use_ftp_bit = 0 END /* ** Parameter check: @publication_type ** Must be 0 - Transactional or 1 - Snapshot */ IF @publication_type NOT IN (0, 1) BEGIN RAISERROR (20033, 16, -1) RETURN (1) END /* ** Parameter Check: @dts_package_location ** Valid values: ** distributor ** subscriber ** */ IF LOWER(@dts_package_location collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('distributor', 'subscriber') BEGIN RAISERROR(21179, 16, -1) RETURN (1) END declare @dts_package_location_id int IF LOWER(@dts_package_location collate SQL_Latin1_General_CP1_CS_AS) = 'distributor' SELECT @dts_package_location_id = 0 ELSE SELECT @dts_package_location_id = 1 -- Have to be a push, non updatable subscription to set DTS package name if @dts_package_name is not null begin if @update_mode_id != 0 begin RAISERROR(21180, 16, -1) RETURN (1) end end -- Copy the passwords to new value before attempting to encrypt set @distributor_enc_password = @distributor_password IF (@encrypted_distributor_password = 0) -- Encrypt the password BEGIN EXEC @retcode = master.dbo.xp_repl_encrypt @distributor_enc_password OUTPUT IF @@error <> 0 OR @retcode <> 0 return 1 END declare @dts_package_enc_password nvarchar(524) set @dts_package_enc_password = @dts_package_password if @dts_package_enc_password is not null begin EXEC @retcode = master.dbo.xp_repl_encrypt @dts_package_enc_password OUTPUT IF @@error <> 0 OR @retcode <> 0 return 1 end /* ** Parameter Check: @offloadserver ** 1. If @offloadagent = 'true' then @offloadserver cannot be null. ** 2. Similar to the push case, we don't allow "remote" activation ** of agent on the local machine. */ SELECT @offloadagent = LOWER(@offloadagent collate SQL_Latin1_General_CP1_CS_AS) IF @offloadagent NOT IN ('true', 'false') BEGIN RAISERROR (14148, 16, -1, '@offloadagent') RETURN (1) END IF @offloadagent = 'true' BEGIN SELECT @offload_agent_bit = 1 END ELSE BEGIN SELECT @offload_agent_bit = 0 END IF @offload_agent_bit = 1 AND (@offloadserver is NULL or @offloadserver = N'') BEGIN RAISERROR(21215, 16, -1) RETURN (1) END IF UPPER(@offloadserver) = UPPER(@@SERVERNAME) AND @offload_agent_bit = 1 BEGIN RAISERROR(21227, 16, -1) RETURN (1) END EXEC @retcode = sp_MSreplcheckoffloadserver @offloadserver IF @retcode <> 0 OR @@ERROR <> 0 RETURN (1) /* ** Construct unique name */ if @subscriber is NULL select @subscriber = '' if @subscriber_db is NULL select @subscriber_db = '' declare @job_existing bit if @job_name is null begin select @job_existing = 0 SELECT @job_name = CONVERT(nvarchar(18),@publisher ) + '-' + CONVERT(nvarchar(18),@publisher_db) + '-' + CONVERT(nvarchar(18),@publication) + '-' + CONVERT(nvarchar(18),@subscriber) + '-' + CONVERT(nvarchar(18),@subscriber_db) + '-' + CONVERT(nvarchar(36),newid()) end else select @job_existing = 1 -- Get property values. if @reserved = 'no_change_to_properties' begin -- Get the distributor value. It will be used in agent command line. select @distributor = distributor, @enabled_for_syncmgr = case enabled_for_syncmgr when 0 then 'false' when 1 then 'true' end from MSsubscription_properties where UPPER(publisher) = UPPER(@publisher) and publisher_db = @publisher_db and publication = @publication end BEGIN TRAN /* ** If the publication is independent agent type or it is the first ** subscription on the non independent agent publications. */ IF @independent_agent_id = 1 OR NOT EXISTS (SELECT * FROM MSreplication_subscriptions WHERE UPPER(@publisher) = UPPER(publisher) and @publisher_db = publisher_db and agent_id IS NOT NULL and independent_agent = 0) BEGIN if @job_existing = 0 begin /* Construct agent command */ SELECT @command = '-Publisher ' + @publisher + ' ' SELECT @command = @command + '-PublisherDB ' + QUOTENAME(@publisher_db) + ' ' IF @independent_agent_id = 1 SELECT @command = @command + '-Publication ' + QUOTENAME(@publication) + ' ' SELECT @command = @command + '-Distributor ' + QUOTENAME(@distributor) + ' ' /* Use -Xdatabase to save command line space We can not use -Xserver for distribution because SQLExec will validate the server to be in sysservers. SELECT @command = @command + '-DistributionDB ' + QUOTENAME(@distribution_db) + ' ' */ SELECT @command = @command + '-SubscriptionType ' + convert(nvarchar(10),@subscription_type_id) + ' ' SELECT @command = @command + '-Subscriber ' + QUOTENAME(@subscriber) + ' ' select @command = @command + '-SubscriberSecurityMode ' + convert(nvarchar(10),@subscriber_security_mode) + ' ' if @subscriber_login is not NULL select @command = @command + '-SubscriberLogin ' + quotename(@subscriber_login) + ' ' if @subscriber_password is not NULL begin set @subscriber_enc_password = @subscriber_password exec @retcode = master.dbo.xp_repl_encrypt @subscriber_enc_password OUTPUT select @command = @command + '-SubscriberEncryptedPassword ' + quotename(@subscriber_enc_password) + ' ' end SELECT @command = @command + '-SubscriberDB ' + QUOTENAME(@subscriber_db) + ' ' if @dts_package_name is not null select @command = @command + '-UseDTS ' if @offload_agent_bit = 1 select @command = @command + N'-Offload ' + @offloadserver + N' ' /* ** make sure the command line is not truncated */ /* Use datalength because len doesn't count the last space in @command */ IF (datalength(@command) + datalength(@optional_command_line)) > 8000 BEGIN RAISERROR(20018, 16, -1) RETURN(1) END SELECT @command = @command + @optional_command_line -- Get Distribution category name (assumes category_id = 10) select @category_name = name FROM msdb.dbo.syscategories where category_id = 10 EXEC @retcode = dbo.sp_MSadd_repl_job @name = @job_name, @subsystem = 'Distribution', @server = @@SERVERNAME, @databasename = @distribution_db, @enabled = 1, @freqtype = @frequency_type, @freqinterval = @frequency_interval, @freqsubtype = @frequency_subday, @freqsubinterval = @frequency_subday_interval, @freqrelativeinterval = @frequency_relative_interval, @freqrecurrencefactor = @frequency_recurrence_factor, @activestartdate = @active_start_date, @activeenddate = @active_end_date, @activestarttimeofday = @active_start_time_of_day, @activeendtimeofday = @active_end_time_of_day, @command = @command, @category_name = @category_name, @retryattempts = 10, @retrydelay = 1, @job_id = @distribution_jobid OUTPUT IF @@ERROR <> 0 or @retcode <> 0 BEGIN IF @@TRANCOUNT = 1 ROLLBACK TRAN ELSE COMMIT TRAN RETURN(1) END end else begin select @distribution_jobid = job_id from msdb..sysjobs_view where name = @job_name collate database_default and UPPER(originating_server) = UPPER(CONVERT(sysname, SERVERPROPERTY('ServerName'))) if @distribution_jobid IS NULL begin -- Message from msdb.dbo.sp_verify_job_identifiers RAISERROR(14262, -1, -1, 'Job', @job_name) IF @@TRANCOUNT = 1 ROLLBACK TRAN ELSE COMMIT TRAN RETURN(1) end end END if @reserved <> 'no_change_to_properties' and (@subscription_type_id = 1) OR (@subscription_type_id = 2) BEGIN IF NOT EXISTS (select * from MSsubscription_properties where UPPER(publisher) = UPPER(@publisher) and publisher_db = @publisher_db and publication = @publication) BEGIN -- Publication type: -- 0 transactional -- 1 snapshot -- 2 merge (not allowed) INSERT INTO MSsubscription_properties (publisher, publisher_db, publication, publication_type, publisher_login,publisher_password, publisher_security_mode, distributor, distributor_login, distributor_password, distributor_security_mode, ftp_address, ftp_port, ftp_login, ftp_password, alt_snapshot_folder, working_directory, use_ftp, dts_package_name, dts_package_password, dts_package_location, offload_agent, offload_server, dynamic_snapshot_location) values (@publisher, @publisher_db, @publication, @publication_type, NULL, NULL, 1, @distributor, @distributor_login, @distributor_enc_password, @distributor_security_mode, null, null, null, null, @alt_snapshot_folder, @working_directory, @use_ftp_bit, @dts_package_name, @dts_package_enc_password, @dts_package_location_id, @offload_agent_bit, @offloadserver, null) IF @@ERROR <> 0 BEGIN IF @@TRANCOUNT = 1 ROLLBACK TRAN ELSE COMMIT TRAN RETURN(1) END END ELSE BEGIN update MSsubscription_properties set distributor = @distributor, distributor_login = @distributor_login, distributor_password = @distributor_enc_password, distributor_security_mode = @distributor_security_mode, dts_package_name = @dts_package_name, dts_package_password = @dts_package_enc_password, dts_package_location = @dts_package_location_id where UPPER(publisher) = UPPER(@publisher) and publisher_db = @publisher_db and publication = @publication END -- For dependent subscriptions we need to fix up all the -- shared properties IF @independent_agent_id = 0 BEGIN EXEC @retcode = sp_MSfixupsharedagentproperties @publisher = @publisher, @publisher_db = @publisher_db, @publication = @publication, @distributor = @distributor, @distributor_security_mode = @distributor_security_mode, @distributor_login = @distributor_login, @distributor_password = @distributor_enc_password, @ftp_address = @ftp_address, @ftp_port = @ftp_port, @ftp_login = @ftp_login, @ftp_password = @ftp_password, @alt_snapshot_folder = @alt_snapshot_folder, @working_directory = @working_directory, @use_ftp = @use_ftp_bit, @offload_agent = @offload_agent_bit, @offload_server = @offloadserver IF @retcode <> 0 OR @@ERROR <> 0 BEGIN IF @@TRANCOUNT = 1 ROLLBACK TRAN ELSE COMMIT TRAN RETURN(1) END END IF @@ERROR <> 0 BEGIN IF @@TRANCOUNT = 1 ROLLBACK TRAN ELSE COMMIT TRAN RETURN(1) END END /* If we do not have independent agents , i.e. independent_agent=0, but there is already a row for that publisher and that publisher database with a NOT null distribution_agent_id, then set the @distribution_jobid to that id. Note that if there are no rows returned, the value of the variable does not change, which is what we want. There should never be more than one row ever returned for this query - but will use TOP 1 to insist that is the case. */ IF @independent_agent_id = 0 BEGIN SELECT DISTINCT @distribution_jobid=agent_id, @job_name = distribution_agent FROM MSreplication_subscriptions WHERE UPPER(publisher) = UPPER(@publisher) AND publisher_db = @publisher_db AND agent_id IS NOT NULL AND independent_agent=0 END UPDATE MSreplication_subscriptions SET distribution_agent = @job_name, agent_id = @distribution_jobid WHERE UPPER(publisher) = UPPER(@publisher) AND publisher_db = @publisher_db AND publication = @publication AND (subscription_type = 1 /* pull*/ OR subscription_type = 2) /*anonymous*/ IF @@ERROR <> 0 BEGIN IF @@TRANCOUNT = 1 ROLLBACK TRAN ELSE COMMIT TRAN RETURN(1) END /* Conditional support for MobileSync */ if LOWER(@enabled_for_syncmgr collate SQL_Latin1_General_CP1_CS_AS) = 'true' BEGIN /* Call sp_MSregistersubscription so that the subscription can be synchronized via MobileSync etc. */ declare @subscription_id uniqueidentifier declare @failover_mode_id int set @subscription_id = convert(uniqueidentifier, @distribution_jobid) if @update_mode_id in (3,5) select @failover_mode_id = 1 else if @update_mode_id in (2,4) select @failover_mode_id = 2 else select @failover_mode_id = 0 exec @retcode = dbo.sp_MSregistersubscription @replication_type = 1, @publisher = @publisher, @publisher_db = @publisher_db, @publication = @publication, @subscriber = @subscriber, @subscriber_db = @subscriber_db, @subscriber_security_mode = @subscriber_security_mode, @subscriber_login = @subscriber_login, @subscriber_password = @subscriber_password, @distributor = @distributor, @subscription_id = @subscription_id, @independent_agent = @independent_agent_id, @subscription_type = @subscription_type_id, @failover_mode = @failover_mode_id IF @@ERROR <> 0 or @retcode <> 0 BEGIN IF @@TRANCOUNT = 1 ROLLBACK TRAN ELSE COMMIT TRAN RETURN(1) END END COMMIT TRAN RETURN(0) GO raiserror('Creating procedure sp_helpsubscription_properties ', 0,1) go CREATE PROCEDURE sp_helpsubscription_properties @publisher sysname = '%', @publisher_db sysname = '%', @publication sysname = '%', @publication_type int = NULL AS SET NOCOUNT ON DECLARE @retcode int /* ** Security Check */ EXEC @retcode = dbo.sp_MSreplcheck_subscribe IF @@ERROR <> 0 or @retcode <> 0 RETURN(1) /* ** The logic is added here for the case where MSsubscription_properties table does not exist ** or relevant entry is not added because sp_addmergepullsubscription_agent or sp_addsubscription_agent ** is not called. */ IF NOT EXISTS (select * from sysobjects where name = 'MSsubscription_properties' and type = 'U') begin return (0) end IF (@publisher IS NULL) OR (@publisher = '') select @publisher = '%' IF (@publisher_db IS NULL) OR (@publisher_db = '') select @publisher_db = '%' IF (@publication IS NULL) OR (@publication = '') select @publication = '%' IF @publication_type IS NOT NULL BEGIN SELECT publisher, publisher_db, publication, publication_type, publisher_login, publisher_password, publisher_security_mode, distributor, distributor_login, distributor_password, distributor_security_mode, 'ftp_address' = null, 'ftp_port' = 0, 'ftp_login' = null, 'ftp_password' = null, alt_snapshot_folder, working_directory, use_ftp, dts_package_name, dts_package_password, dts_package_location, offload_agent, offload_server, dynamic_snapshot_location FROM MSsubscription_properties WHERE ((@publisher = N'%') OR (UPPER(publisher) = UPPER(@publisher))) AND ((@publisher_db = N'%') or ( publisher_db = @publisher_db)) AND publication LIKE @publication AND publication_type = @publication_type END ELSE BEGIN SELECT publisher, publisher_db, publication, publication_type, publisher_login, publisher_password, publisher_security_mode, distributor, distributor_login, distributor_password, distributor_security_mode, 'ftp_address' = null, 'ftp_port' = 0, 'ftp_login' = null, 'ftp_password' = null, alt_snapshot_folder, working_directory, use_ftp, dts_package_name, dts_package_password, dts_package_location, offload_agent, offload_server, dynamic_snapshot_location FROM MSsubscription_properties WHERE ((@publisher = N'%') OR (UPPER(publisher) = UPPER(@publisher))) AND ((@publisher_db = N'%') or ( publisher_db = @publisher_db)) AND publication LIKE @publication END RETURN (0) GO EXEC dbo.sp_MS_marksystemobject sp_helpsubscription_properties GO raiserror('Creating procedure sp_change_subscription_properties', 0,1) go CREATE PROCEDURE sp_change_subscription_properties @publisher sysname, @publisher_db sysname, @publication sysname, @property sysname, @value nvarchar(1000), @publication_type int = NULL AS SET NOCOUNT ON DECLARE @command nvarchar(2000) DECLARE @column_to_update nvarchar(64) DECLARE @value_string nvarchar(255) DECLARE @independent_agent bit DECLARE @retcode int DECLARE @subscription_type int DECLARE @intvalue int DECLARE @value_bit bit DECLARE @offload_agent bit DECLARE @offload_server sysname DECLARE @dbname sysname DECLARE @local_publication sysname DECLARE @agentid binary(16) DECLARE @local_publisher sysname DECLARE @cursor_opened bit DECLARE @cursor_allocated bit DECLARE @agenttype nvarchar(20) DECLARE @commandline nvarchar(3200) SELECT @cursor_opened = 0 SELECT @cursor_allocated = 0 SELECT @retcode = 0 /* ** Security Check */ EXEC @retcode = dbo.sp_MSreplcheck_subscribe IF @@ERROR <> 0 or @retcode <> 0 RETURN(1) IF NOT EXISTS (select * from sysobjects where name = 'MSsubscription_properties' and type = 'U') begin raiserror(14027, 16, -1, 'The subscription properties table ''MSsubscription_properties''') return (1) end if (@publisher is null) begin raiserror(14043, 16, -1, '@publisher') return (1) end if(@publisher_db is null) begin raiserror(14043, 16, -1, '@publisher_db') return (1) end if (@publication is null) or (@publication = '') begin select @publication = '%' end -- Expand '%' into individual subscriptions using a cursor IF @publication = N'%' BEGIN BEGIN TRANSACTION subscription_properties_exp DECLARE hsubprop CURSOR LOCAL FAST_FORWARD FOR SELECT publication FROM MSreplication_subscriptions WHERE UPPER(publisher) = UPPER(@publisher) AND publisher_db = @publisher_db -- NOTE: publication like '%' is implicit IF @@ERROR <> 0 GOTO ExpFailure SELECT @cursor_allocated = 1 OPEN hsubprop IF @@ERROR <> 0 GOTO ExpFailure SELECT @cursor_opened = 1 FETCH hsubprop INTO @local_publication WHILE (@@FETCH_STATUS <> 0) BEGIN EXEC @retcode = sp_change_subscription_properties @publisher = @publisher, @publisher_db = @publisher_db, @publication = @local_publication, @property = @property, @value = @value, @publication_type = @publication_type IF @retcode <> 0 OR @@ERROR <> 0 GOTO ExpFailure FETCH hsubprop INTO @local_publication END CLOSE hsubprop DEALLOCATE hsubprop COMMIT TRANSACTION subscription_properties_exp IF @@ERROR <> 0 GOTO ExpFailure RETURN (0) ExpFailure: IF @cursor_opened = 1 CLOSE hsubprop IF @cursor_allocated = 1 DEALLOCATE hsubprop ROLLBACK TRANSACTION subscription_properties_exp RETURN (1) END -- Check for existence of the specified pull subscription SELECT @agentid = NULL SELECT @local_publisher = NULL SELECT @dbname = DB_NAME() IF @publication_type IN (0,1) OR @publication_type IS NULL BEGIN IF EXISTS (SELECT * FROM sysobjects WHERE id = object_id('MSreplication_subscriptions')) BEGIN SELECT @local_publisher = publisher, @agentid = agent_id FROM MSreplication_subscriptions WHERE UPPER(publisher) = UPPER(@publisher) AND publisher_db = @publisher_db AND publication = @publication END END IF @publication_type = 2 OR (@publication_type IS NULL AND @local_publisher IS NULL) BEGIN IF EXISTS (SELECT * FROM sysobjects WHERE id = object_id('sysmergepublications')) BEGIN SELECT @local_publisher = mp.publisher, @agentid = mr.merge_jobid FROM sysmergepublications mp INNER JOIN sysmergesubscriptions ms ON mp.pubid = ms.pubid AND UPPER(mp.publisher) = UPPER(@publisher) AND mp.publisher_db = @publisher_db AND mp.name = @publication AND ms.db_name = @dbname AND UPPER(ms.subscriber_server) = UPPER(@@SERVERNAME) INNER JOIN MSmerge_replinfo mr ON ms.subid = mr.repid END END IF @local_publisher IS NULL BEGIN RAISERROR(21226, 16, -1, @dbname) RETURN (1) END SELECT @offload_agent = NULL SELECT @offload_server = NULL SELECT @offload_agent = offload_agent, @offload_server = offload_server, @publication_type = publication_type FROM MSsubscription_properties WHERE UPPER(publisher) = UPPER(@publisher) AND publisher_db = @publisher_db AND publication = @publication -- If the subscription does not have a corresponding entry in MSsubscription_properties, -- the subscription is probably created by the ActiveX control. In this case there isn't much -- we can do about it so we just return 0. IF @offload_agent IS NULL BEGIN RETURN (0) END IF (@property IS NULL) begin raiserror(14043, 16, -1, '@property') return (1) end ELSE IF (lower(@property collate SQL_Latin1_General_CP1_CS_AS) = 'publisher_login') select @column_to_update = 'publisher_login' ELSE IF (lower(@property collate SQL_Latin1_General_CP1_CS_AS) = 'publisher_password') begin select @column_to_update = 'publisher_password' EXEC @retcode = master.dbo.xp_repl_encrypt @value OUTPUT IF @@error <> 0 OR @retcode <> 0 return 1 end ELSE IF (lower(@property collate SQL_Latin1_General_CP1_CS_AS) = 'publisher_security_mode') select @column_to_update = 'publisher_security_mode' ELSE IF (lower(@property collate SQL_Latin1_General_CP1_CS_AS) = 'distributor') select @column_to_update = 'distributor' ELSE IF (lower(@property collate SQL_Latin1_General_CP1_CS_AS) = 'distributor_login') select @column_to_update = 'distributor_login' ELSE IF (lower(@property collate SQL_Latin1_General_CP1_CS_AS) = 'distributor_password') begin select @column_to_update = 'distributor_password' EXEC @retcode = master.dbo.xp_repl_encrypt @value OUTPUT IF @@error <> 0 OR @retcode <> 0 return 1 end ELSE IF (lower(@property collate SQL_Latin1_General_CP1_CS_AS) = 'distributor_security_mode') select @column_to_update = 'distributor_security_mode' ELSE IF (lower(@property collate SQL_Latin1_General_CP1_CS_AS) = 'ftp_address') select @column_to_update = 'ftp_address' ELSE IF (lower(@property collate SQL_Latin1_General_CP1_CS_AS) = 'ftp_port') select @column_to_update = 'ftp_port' ELSE IF (lower(@property collate SQL_Latin1_General_CP1_CS_AS) = 'ftp_login') select @column_to_update = 'ftp_login' ELSE IF (lower(@property collate SQL_Latin1_General_CP1_CS_AS) = 'ftp_password') select @column_to_update = 'ftp_password' ELSE IF (lower(@property collate SQL_Latin1_General_CP1_CS_AS) = 'alt_snapshot_folder') BEGIN select @column_to_update = 'alt_snapshot_folder' END ELSE IF (lower(@property collate SQL_Latin1_General_CP1_CS_AS) = 'working_directory') BEGIN select @column_to_update = 'working_directory' END ELSE IF (lower(@property collate SQL_Latin1_General_CP1_CS_AS) = 'use_ftp') select @column_to_update = 'use_ftp' ELSE IF (lower(@property collate SQL_Latin1_General_CP1_CS_AS) = 'dts_package_name') select @column_to_update = 'dts_package_name' ELSE IF (lower(@property collate SQL_Latin1_General_CP1_CS_AS) = 'dts_package_password') begin select @column_to_update = 'dts_package_password' EXEC @retcode = master.dbo.xp_repl_encrypt @value OUTPUT IF @@error <> 0 OR @retcode <> 0 return 1 end ELSE IF (lower(@property collate SQL_Latin1_General_CP1_CS_AS) = 'dts_package_location') select @column_to_update = 'dts_package_location' ELSE IF (lower(@property collate SQL_Latin1_General_CP1_CS_AS) = 'offload_agent') BEGIN select @column_to_update = 'offload_agent' END ELSE IF (lower(@property collate SQL_Latin1_General_CP1_CS_AS) = 'offload_server') BEGIN select @column_to_update = 'offload_server' exec @retcode = sp_MSreplcheckoffloadserver @value if @retcode <> 0 or @@error <> 0 return(1) END ELSE IF (lower(@property collate SQL_Latin1_General_CP1_CS_AS) = N'dynamic_snapshot_location') and @publication_type = 2 BEGIN select @column_to_update = N'dynamic_snapshot_location' END ELSE BEGIN raiserror (3217, 16, -1, '@property') return(1) END IF @column_to_update in ('use_ftp', 'offload_agent') BEGIN IF LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) = N'true' BEGIN SELECT @value_bit = 1 END ELSE IF LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) = N'false' BEGIN SELECT @value_bit = 0 END ELSE BEGIN RAISERROR(14137, 16, -1) END END IF (lower(@property collate SQL_Latin1_General_CP1_CS_AS) = 'distributor_security_mode') OR (lower(@property collate SQL_Latin1_General_CP1_CS_AS) = 'publisher_security_mode') BEGIN IF NOT ( @value = 0 or @value = 1 or (@value = 2 and lower(@property collate SQL_Latin1_General_CP1_CS_AS) = 'publisher_security_mode' )) BEGIN raiserror(3217, 16, -1, '@value') return(1) END select @value_string = convert(nvarchar(1), @value) END ELSE IF (lower(@property collate SQL_Latin1_General_CP1_CS_AS) = 'dts_package_location') BEGIN IF LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) = N'distributor' select @value_string = '0' ELSE IF LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) = N'subscriber' select @value_string = '1' ELSE begin raiserror(20587, 16, -1, 'dts_package_location', 'sp_change_subscription_properties') return(1) end END ELSE BEGIN IF @value IS NULL BEGIN select @value_string = 'null' END ELSE BEGIN select @value_string = 'N' + quotename(rtrim(@value),'''') END END -- Ignore ftp_address, ftp_port, ftp_login, ftp_password on post 7.0 servers IF (@column_to_update IN (N'ftp_address', N'ftp_port', N'ftp_login', N'ftp_password')) BEGIN RETURN (0) END -- If the 'offload_agent' property is 1, 'offload_server' property must not be -- null or empty. Make sure that this is the case IF (@column_to_update = N'offload_agent' AND @value_bit = 1 AND (@offload_server IS NULL OR @offload_server = N'')) BEGIN RAISERROR(21215, 16, -1) RETURN(1) END -- If we are enabling agent offload for this pull subscription, -- we should make sure that the offload server is different from -- the Subscriber's server name IF (@column_to_update = N'offload_agent' AND @value_bit = 1 AND UPPER(@offload_server) = UPPER(@@SERVERNAME)) OR (@column_to_update = N'offload_server' AND @offload_agent = 1 AND UPPER(@value) = UPPER(@@SERVERNAME)) BEGIN RAISERROR(21227, 16, -1) RETURN (1) END BEGIN TRANSACTION subscription_properties IF (lower(@property collate SQL_Latin1_General_CP1_CS_AS) = 'use_ftp') begin update MSsubscription_properties set use_ftp = @value_bit where UPPER(publisher) = UPPER(@publisher) and publisher_db = @publisher_db and publication = @publication IF @@error <> 0 OR @retcode <> 0 GOTO Failure end else if (lower(@property collate SQL_Latin1_General_CP1_CS_AS) = 'offload_agent') begin update MSsubscription_properties set offload_agent = @value_bit where UPPER(publisher) = UPPER(@publisher) and publisher_db = @publisher_db and publication = @publication IF @@error <> 0 OR @retcode <> 0 GOTO Failure -- Call helper procedure to add or remove the '-Offload' parameter -- from the agent's command line in msdb. By now, we should -- have the publication type and the agent jodid. -- Don't do anything if the offload_agent property hasn't been changed IF @offload_agent <> @value_bit BEGIN IF @publication_type IN (0,1) BEGIN SELECT @agenttype = N'distribution' END ELSE BEGIN SELECT @agenttype = N'merge' END -- Add or remove the Offload parameter based on the new value -- of the offload_agent property IF @value_bit = 0 BEGIN EXEC @retcode = sp_MSremoveoffloadparameter @job_id = @agentid, @agenttype = @agenttype IF @@ERROR <> 0 OR @retcode <> 0 GOTO Failure END ELSE BEGIN EXEC @retcode = sp_MSaddoffloadparameter @job_id = @agentid, @offloadserver = @offload_server, @agenttype = @agenttype IF @@ERROR <> 0 OR @retcode <> 0 GOTO Failure END END end else if lower(@property collate SQL_Latin1_General_CP1_CS_AS) = N'dynamic_snapshot_location' begin select @value = rtrim(ltrim(@value)) update MSsubscription_properties set dynamic_snapshot_location = @value where upper(publisher) = upper(@publisher) and publisher_db = @publisher_db and publication = @publication if @@error <> 0 or @retcode <> 0 goto Failure -- Call helper functions to add/update or remove the -DynamicSnapshotLocationParameter if @value is null or @value = N'' begin update msdb.dbo.sysjobsteps set command = fn_removeparameterwithargument(command, N'DynamicSnapshotLocation') collate database_default where job_id = @agentid and lower(subsystem collate SQL_Latin1_General_CP1_CS_AS) = N'merge' end else begin select @commandline = command from msdb.dbo.sysjobsteps where job_id = @agentid and lower(subsystem collate SQL_Latin1_General_CP1_CS_AS) = N'merge' select @commandline = fn_updateparameterwithargument(@commandline, N'DynamicSnapshotLocation', fn_replquotename(@value)) collate database_default -- Need to remove existing alternate snapshot folder parameters -- and file transfer type parameters select @commandline = fn_removeparameterwithargument(@commandline, N'FileTransferType') collate database_default select @commandline = fn_removeparameterwithargument(@commandline, N'AltSnapshotFolder') collate database_default update msdb.dbo.sysjobsteps set command = @commandline where job_id = @agentid and lower(subsystem collate SQL_Latin1_General_CP1_CS_AS) = N'merge' end end else begin -- Password is encrypted. Must prefix every string with N' -- otherwise, the chars will be convert to '???' select @command = N'update MSsubscription_properties set ' + @column_to_update + '= ' + @value_string + ' where UPPER(publisher) = UPPER(' + quotename(@publisher,'''') + ') and publisher_db = ' + quotename(@publisher_db, '''') + ' and publication = ' + quotename(@publication,'''') EXEC (@command) IF @@error <> 0 OR @retcode <> 0 GOTO Failure end -- If the offload_server property is chnaged, we have to modify the agent's -- command line if the agent has already been enabled for remote activation IF @column_to_update = N'offload_server' AND @offload_agent = 1 BEGIN IF @publication_type IN (0,1) BEGIN SELECT @agenttype = N'distribution' END ELSE BEGIN SELECT @agenttype = N'merge' END EXEC @retcode = sp_MSaddoffloadparameter @job_id = @agentid, @offloadserver = @value, @agenttype = @agenttype IF @retcode <> 0 OR @@ERROR <> 0 GOTO Failure END IF (@publication_type = 0 or @publication_type = 1) AND @publication <> N'%' AND @column_to_update IN ('distributor', 'distributor_login', 'distributor_password', 'distributor_security_mode', 'ftp_address', 'ftp_port', 'ftp_login', 'ftp_password', 'alt_snapshot_folder', 'working_dir', 'use_ftp', 'offload_agent', 'offload_server') BEGIN SELECT @subscription_type = subscription_type FROM MSreplication_subscriptions WHERE UPPER(publisher) = UPPER(@publisher) AND publisher_db = @publisher_db AND publication = @publication IF @@error <> 0 OR @retcode <> 0 GOTO Failure -- Update the property for all shared subscriptions IF @column_to_update IN ('distributor_security_mode', 'ftp_port') BEGIN SELECT @intvalue = CONVERT(int, @value) EXEC @retcode = sp_MSupdatesharedagentproperties @publisher = @publisher, @publisher_db = @publisher_db, @publication = @publication, @property = @column_to_update, @intvalue = @intvalue, @subscription_type = @subscription_type END ELSE IF @column_to_update IN ('use_ftp', 'offload_agent') BEGIN EXEC @retcode = sp_MSupdatesharedagentproperties @publisher = @publisher, @publisher_db = @publisher_db, @publication = @publication, @property = @column_to_update, @intvalue = @value_bit, @subscription_type = @subscription_type END ELSE BEGIN EXEC @retcode = sp_MSupdatesharedagentproperties @publisher = @publisher, @publisher_db = @publisher_db, @publication = @publication, @property = @column_to_update, @strvalue = @value, @subscription_type = @subscription_type END IF @@error <> 0 OR @retcode <> 0 GOTO Failure END -- Ftp and alternate snapshot folder are mutually -- exclusive options but instead of raising an error -- when both of them are non-null, nullify the other -- property when either one of them is set to non-null -- value since properties can only be set one at a time -- 'dynamic_snapshot_location' should also be added to the -- list of mutually exclusive properties IF (@column_to_update = 'ftp_address') AND (@value <> N'' AND @value IS NOT NULL) BEGIN EXEC @retcode = sp_change_subscription_properties @publisher = @publisher, @publisher_db = @publisher_db, @publication = @publication, @property = 'alt_snapshot_folder', @value = NULL IF @@error <> 0 OR @retcode <> 0 GOTO Failure END IF (@column_to_update = 'use_ftp') AND (@value_bit = 1) BEGIN EXEC @retcode = sp_change_subscription_properties @publisher = @publisher, @publisher_db = @publisher_db, @publication = @publication, @property = 'alt_snapshot_folder', @value = NULL IF @@error <> 0 OR @retcode <> 0 GOTO Failure IF @publication_type = 2 BEGIN EXEC @retcode = sp_change_subscription_properties @publisher = @publisher, @publisher_db = @publisher_db, @publication = @publication, @property = 'dynamic_snapshot_location', @value = NULL IF @@error <> 0 OR @retcode <> 0 GOTO Failure END END IF (@column_to_update = 'alt_snapshot_folder') AND (@value <> N'' AND @value IS NOT NULL) BEGIN EXEC @retcode = sp_change_subscription_properties @publisher = @publisher, @publisher_db = @publisher_db, @publication = @publication, @property = 'ftp_address', @value = NULL IF @@error <> 0 OR @retcode <> 0 GOTO Failure EXEC @retcode = sp_change_subscription_properties @publisher = @publisher, @publisher_db = @publisher_db, @publication = @publication, @property = 'use_ftp', @value = 'false' IF @@error <> 0 OR @retcode <> 0 GOTO Failure IF @publication_type = 2 BEGIN EXEC @retcode = sp_change_subscription_properties @publisher = @publisher, @publisher_db = @publisher_db, @publication = @publication, @property = 'dynamic_snapshot_location', @value = NULL IF @@error <> 0 OR @retcode <> 0 GOTO Failure END END IF (@column_to_update = 'dynamic_snapshot_location') AND (@value <> N'' AND @value IS NOT NULL) BEGIN EXEC @retcode = sp_change_subscription_properties @publisher = @publisher, @publisher_db = @publisher_db, @publication = @publication, @property = 'ftp_address', @value = NULL IF @@error <> 0 OR @retcode <> 0 GOTO Failure EXEC @retcode = sp_change_subscription_properties @publisher = @publisher, @publisher_db = @publisher_db, @publication = @publication, @property = 'use_ftp', @value = 'false' IF @@error <> 0 OR @retcode <> 0 GOTO Failure EXEC @retcode = sp_change_subscription_properties @publisher = @publisher, @publisher_db = @publisher_db, @publication = @publication, @property = 'alt_snapshot_folder', @value = NULL IF @@error <> 0 OR @retcode <> 0 GOTO Failure END -- Turn off the offload agent bit if the -- the new value of offload server happens to be null -- or empty IF (@column_to_update = 'offload_server' AND (@value IS NULL OR @value = N'') AND @offload_agent = 1) BEGIN EXEC @retcode = sp_change_subscription_properties @publisher = @publisher, @publisher_db = @publisher_db, @publication = @publication, @property = 'offload_agent', @value = 'false' IF @@error <> 0 OR @retcode <> 0 GOTO Failure END IF @@error <> 0 OR @retcode <> 0 GOTO Failure COMMIT TRANSACTION subscription_properties RETURN (0) Failure: ROLLBACK TRANSACTION subscription_properties RETURN (1) GO EXEC dbo.sp_MS_marksystemobject sp_change_subscription_properties GO grant execute on dbo.sp_change_subscription_properties to public raiserror('Creating procedure sp_MSget_pullsubsagent_owner', 0,1) go CREATE PROCEDURE sp_MSget_pullsubsagent_owner ( @publisher sysname, @publisher_db sysname, @publication sysname, /* publication name */ @owner_sid varbinary(85) OUTPUT ) AS declare @job_id uniqueidentifier set nocount on select @owner_sid = null if exists (select * from sysobjects where type = 'U' and name = 'MSreplication_subscriptions') begin -- Get the job_id corresponding to the publication select @job_id = agent_id from MSreplication_subscriptions where upper(@publisher) = upper(publisher) and @publisher_db = publisher_db and @publication = publication -- Using the job_id in MSsubscription properties to get the owner_sid -- in msdb..sysjobs select @owner_sid = owner_sid from msdb..sysjobs where @job_id = job_id end go exec dbo.sp_MS_marksystemobject 'sp_MSget_pullsubsagent_owner' raiserror('Creating procedure sp_droppullsubscription', 0,1) go CREATE PROCEDURE sp_droppullsubscription ( @publisher sysname, @publisher_db sysname, @publication sysname, /* publication name */ @reserved bit = 0 ) AS SET NOCOUNT ON /* ** Declarations. */ DECLARE @name nvarchar(255) DECLARE @retcode int DECLARE @agent_id binary(16) DECLARE @publisher_ex sysname /* Expression used in the cursor */ DECLARE @publisher_db_ex sysname /* Expression used in the cursor */ DECLARE @publication_ex sysname /* Expression used in the cursor */ DECLARE @expanded bit DECLARE @subscription_type_id int DECLARE @count_sub int DECLARE @drop_null_pub bit DECLARE @drop_push_bit bit DECLARE @push int DECLARE @implicit_transaction int DECLARE @close_cursor_at_commit int DECLARE @owner_sid varbinary(85) DECLARE @owner_name sysname DECLARE @qualified_publication_name nvarchar(512) /* ** Initialization */ SELECT @expanded = 0 SELECT @drop_null_pub = 0 SELECT @push = 0 /* ** Get the original set value off IMPLICIT_TRANSACTIONS and CURSOR_CLOSE_ON_COMMIT ** before set these two to off */ select @implicit_transaction = 0 select @close_cursor_at_commit = 0 IF (@reserved = 0) BEGIN SELECT @implicit_transaction = @@options & 2 SELECT @close_cursor_at_commit = @@options & 4 SET IMPLICIT_TRANSACTIONS OFF SET CURSOR_CLOSE_ON_COMMIT OFF END /* ** Security Check */ EXEC @retcode = dbo.sp_MSreplcheck_subscribe IF @@ERROR <> 0 or @retcode <> 0 RETURN(1) SELECT @drop_push_bit = 0 /* ** Check parameter and set expressions used by cursor */ /* Publisher */ IF @publisher IS NULL BEGIN RAISERROR (14043, 16, -1, '@publisher') RETURN (1) END IF @publisher = 'all' BEGIN SELECT @publisher_ex = '%' SELECT @expanded = 1 END ELSE BEGIN EXECUTE @retcode = dbo.sp_validname @publisher IF @retcode <> 0 RETURN (1) SELECT @publisher_ex = @publisher END /* Publisher_db */ IF @publisher_db IS NULL BEGIN RAISERROR (14043, 16, -1, '@publisher_db') RETURN (1) END IF @publisher_db = 'all' BEGIN SELECT @publisher_db_ex = '%' select @expanded = 1 END ELSE BEGIN /* EXECUTE @retcode = dbo.sp_validname @publisher_db IF @retcode <> 0 RETURN (1) */ SELECT @publisher_db_ex = @publisher_db END /* ** Publication ** '' is not a valid name but it may be in the publication name in the table. */ IF @publication IS NULL OR @publication = '' BEGIN SELECT @drop_null_pub = 1 END ELSE IF @publication = 'all' BEGIN SELECT @publication_ex = '%' SELECT @expanded = 1 SELECT @drop_null_pub = 1 END ELSE BEGIN EXECUTE @retcode = dbo.sp_validname @publication IF @retcode <> 0 RETURN (1) SELECT @publication_ex = @publication END /* ** Check to see if the subscription table exists */ IF NOT EXISTS (SELECT * FROM sysobjects WHERE type = 'U' AND name = 'MSreplication_subscriptions') BEGIN IF @expanded = 0 BEGIN RAISERROR(14135, 11, -1, @publisher, @publisher_db, @publication) RETURN(1) END ELSE RETURN(0) END IF @expanded = 0 BEGIN /* ** ** Check to see if the subscription entry exists */ IF NOT EXISTS (SELECT * FROM MSreplication_subscriptions WHERE UPPER(publisher) = UPPER(@publisher) AND publisher_db = @publisher_db AND publication = @publication) BEGIN RAISERROR(14135, 11, -1, @publisher, @publisher_db, @publication) RETURN(1) END /* ** Make sure the subscription is not push type if @drop_push_bit = 0 */ IF @drop_push_bit = 0 BEGIN IF EXISTS (SELECT * FROM MSreplication_subscriptions WHERE UPPER(publisher) = UPPER(@publisher) AND publisher_db = @publisher_db AND publication = @publication AND subscription_type = @push AND @drop_push_bit = 0) BEGIN RAISERROR(20017, 16, -1) RETURN(1) END END END ELSE /* ** Open a cursor and call recursively if ** parameters are expanded. */ BEGIN /* ** Note: Any expression check on null value is false ** @subscription_type_id is NULL <==> push ** @subscription_type_id is NOT NULL <==> non push */ -- Have to use static cursor option because DECLARE hCdroppullsubscription CURSOR STATIC LOCAL FORWARD_ONLY FOR SELECT DISTINCT publisher, publisher_db, publication FROM MSreplication_subscriptions WHERE ((@publisher_ex = N'%') OR (UPPER(publisher) = UPPER(@publisher_ex))) AND ((@publisher_db_ex = N'%') OR ( publisher_db = @publisher_db_ex)) AND (publication LIKE @publication_ex OR (@drop_null_pub = 1 AND publication IS NULL)) AND ((@drop_push_bit =0 AND subscription_type <> @push) OR @drop_push_bit = 1) FOR READ ONLY OPEN hCdroppullsubscription FETCH hCdroppullsubscription INTO @publisher, @publisher_db, @publication WHILE (@@fetch_status <> -1) BEGIN EXECUTE @retcode = dbo.sp_droppullsubscription @publisher = @publisher, @publisher_db = @publisher_db, @publication = @publication, @reserved = 1 FETCH hCdroppullsubscription INTO @publisher, @publisher_db, @publication END CLOSE hCdroppullsubscription DEALLOCATE hCdroppullsubscription RETURN (0) END /* ** Only members of the sysadmin group and the creator of the distribution ** agent can drop a pull subscription successfully. This behavior matches ** the behavior of the sysjobs_view. DBO of the subscriber database, ** sysadmins (owner is undefined) can drop a subscription if the owner_sid ** is null. */ EXEC sp_MSget_pullsubsagent_owner @publisher = @publisher, @publisher_db = @publisher_db, @publication = @publication, @owner_sid = @owner_sid OUTPUT IF (@owner_sid is not null AND (SUSER_SID() <> @owner_sid) AND (ISNULL(IS_SRVROLEMEMBER('sysadmin'),0) = 0)) BEGIN SELECT @owner_name = SUSER_SNAME(@owner_sid) SELECT @qualified_publication_name = @publisher + N':' + @publisher_db + N':' + @publication RAISERROR(21121,16,-1,@owner_name, @qualified_publication_name) RETURN (1) END /* ** Get the agent name, it may be dropped later. */ SELECT @agent_id = agent_id FROM MSreplication_subscriptions WHERE UPPER(publisher) = UPPER(@publisher) AND publisher_db = @publisher_db AND publication = @publication -- If the agent is used by other subscription, don't drop it. if (select count(*) from MSreplication_subscriptions where agent_id = @agent_id) > 1 select @agent_id = NULL begin tran save TRAN droppullsubscription /* ** Drop the subscription entry and the distribution agent if it exists */ /* ** If the distribution agent is not used anymore, ** drop the agent if it exists */ IF @agent_id IS NOT NULL BEGIN IF (EXISTS (SELECT * FROM msdb..sysjobs_view WHERE job_id = @agent_id)) BEGIN -- Checks if the job name matches one that is generated -- by replication EXEC @retcode = dbo.sp_MSispulldistributionjobnamegenerated @publisher = @publisher, @publisher_db = @publisher_db, @publication = @publication, @job_id = @agent_id IF @@ERROR <> 0 GOTO UNDO -- Only drop jobs if the name was generated IF @retcode = 0 BEGIN EXEC @retcode = msdb.dbo.sp_delete_job @job_id = @agent_id IF @@ERROR <> 0 or @retcode <> 0 GOTO UNDO -- Delete MSreplication_subsciptions table after dropping -- the distribution agent and delay one second -- to avoid deadlock with it. WAITFOR DELAY '00:00:01' END END END /* Call sp_MSunregistersubscription so that the reg entries get deleted */ declare @subscriber_db sysname set @subscriber_db = DB_NAME() exec @retcode = dbo.sp_MSunregistersubscription @publisher = @publisher, @publisher_db = @publisher_db, @publication = @publication, @subscriber = @@SERVERNAME, @subscriber_db = @subscriber_db IF @retcode<>0 or @@ERROR<>0 GOTO UNDO /* -- Delete MSreplication_subsciptions table after dropping the distribution agent\ -- To avoid deadlock with it. --DELETE MSreplication_subscriptions WHERE UPPER(publisher) = UPPER(@publisher) AND --publisher_db = @publisher_db AND --publication = @publication --IF @@ERROR <> 0 -- GOTO UNDO */ IF EXISTS(select * from sysobjects where type='U' and name = 'MSsubscription_properties') BEGIN DELETE FROM MSsubscription_properties WHERE UPPER(publisher) = UPPER(@publisher) AND publisher_db = @publisher_db AND publication = @publication IF @@ERROR <> 0 GOTO UNDO IF NOT EXISTS (SELECT * FROM MSsubscription_properties) BEGIN exec @retcode = dbo.sp_MSsub_cleanup_prop_table IF @@ERROR <> 0 or @retcode <> 0 GOTO UNDO END END /* ** Clean up metadata at subscriber side */ -- Note: sp_subscription_cleanup should be called after deleting the row -- in MSreplication_subscriptions. exec @retcode = dbo.sp_subscription_cleanup @publisher = @publisher, @publisher_db = @publisher_db, @publication = @publication IF @retcode<>0 or @@ERROR<>0 GOTO UNDO -- -- drop table MSreplication_subscriptions if empty and -- not in recursive call -- IF EXISTS (SELECT * FROM sysobjects WHERE name = 'MSreplication_subscriptions' AND type = 'U') BEGIN IF (@reserved = 0 AND NOT EXISTS (SELECT * FROM MSreplication_subscriptions)) BEGIN DROP TABLE MSreplication_subscriptions IF @@ERROR <> 0 GOTO UNDO END END COMMIT TRAN /* ** set back the two settings if needed */ if @reserved = 0 BEGIN IF @implicit_transaction <>0 SET IMPLICIT_TRANSACTIONS ON IF @close_cursor_at_commit <>0 SET CURSOR_CLOSE_ON_COMMIT ON END RETURN (0) UNDO: IF @@TRANCOUNT > 0 begin ROLLBACK TRAN droppullsubscription COMMIT TRAN end /* ** set back the two settings if needed */ if @reserved = 0 BEGIN IF @implicit_transaction <>0 SET IMPLICIT_TRANSACTIONS ON IF @close_cursor_at_commit <>0 SET CURSOR_CLOSE_ON_COMMIT ON END return 1 go exec sp_MS_marksystemobject 'dbo.sp_droppullsubscription' raiserror('Creating procedure sp_helppullsubscription', 0,1, 0,1) go CREATE PROCEDURE sp_helppullsubscription ( @publisher sysname = '%', @publisher_db sysname = '%', @publication sysname = '%', @show_push nvarchar(5) = 'false' ) AS SET NOCOUNT ON /* ** Declarations. */ DECLARE @command nvarchar(255) DECLARE @name nvarchar(255) DECLARE @retcode int DECLARE @show_push_bit bit DECLARE @push int declare @subscriber sysname declare @subscriber_db sysname declare @publisher_local sysname declare @publisher_db_local sysname declare @publication_local sysname declare @subscription_name nvarchar(1000) declare @regkey nvarchar(1000) declare @syncmgr_keyexist int declare @helpsubscriptioncursor_open int SELECT @push = 0 -- For attach if exists (select * from sysobjects where name = 'MSrepl_restore_stage') -- The database is attached from a subscription copy file without using -- sp_attachsubscription. Return nothing return 0 /* ** Security Check */ EXEC @retcode = dbo.sp_MSreplcheck_subscribe IF @@ERROR <> 0 or @retcode <> 0 RETURN(1) /* ** Initializations. */ set @subscriber = @@SERVERNAME set @subscriber_db = DB_NAME() /* ** Parameter Check: @publisher ** Check to make sure that the publisher is define */ IF @publisher IS NULL BEGIN RAISERROR (14043, 16, -1, '@publisher') RETURN (1) END IF @publisher <> '%' BEGIN EXECUTE @retcode = dbo.sp_validname @publisher IF @@ERROR <> 0 OR @retcode <> 0 RETURN (1) END IF @publication <> '%' BEGIN EXECUTE @retcode = dbo.sp_validname @publication IF @@ERROR <> 0 OR @retcode <> 0 RETURN (1) END IF @show_push IS NOT NULL AND LOWER(@show_push collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('true', 'false') BEGIN RAISERROR (14148, 16, -1, '@show_push') RETURN (1) END IF LOWER(@show_push collate SQL_Latin1_General_CP1_CS_AS) = 'false' SELECT @show_push_bit = 0 IF LOWER(@show_push collate SQL_Latin1_General_CP1_CS_AS) = 'true' SELECT @show_push_bit = 1 IF NOT EXISTS (SELECT * FROM sysobjects WHERE type = 'U' AND name = 'MSreplication_subscriptions') RETURN (0) IF NOT EXISTS (SELECT * FROM sysobjects WHERE type = 'U' AND name = 'MSsubscription_properties') RETURN (0) IF NOT EXISTS (SELECT * FROM sysobjects WHERE type = 'U' AND name = 'MSsubscription_agents') RETURN (0) /* ** Get the result ** ** Note: have to return meta data */ SELECT 'publisher' = rs.publisher, 'publisher database' = rs.publisher_db, 'publication' = rs.publication, 'independent_agent' = rs.independent_agent, 'subscription type' = rs.subscription_type, 'distribution agent' = distribution_agent, 'publication description' = description, 'last updating time' = convert(nvarchar(12), time, 112) + substring(convert(nvarchar(24), time, 121), 11,13), 'subscription_name' = rs.publisher + ':' + rs.publisher_db + ':' + rs.publication, 'last transaction timestamp' = transaction_timestamp, -- SyncTran -- For Queued case, we will return 2/3 for values 4/5 so that -- SQL-DMO does not have to deal with the overloaded values of update_mode 'update_mode' = case when rs.update_mode = 4 then 2 when rs.update_mode = 5 then 3 else rs.update_mode end, 'distribution agent job_id' = agent_id, 'enabled for syncmgr' = enabled_for_syncmgr, 'subscription guid' = subscription_guid, 'subid ' = subid, 'immediate_sync' = immediate_sync, 'publisher_login' = publisher_login, 'publisher_password' = publisher_password, 'publisher_security_mode' = publisher_security_mode, 'distributor' = distributor, 'distributor_login' = distributor_login, 'distributor_password' = distributor_password, 'distributor_security_mode' = distributor_security_mode, 'ftp_address' = ftp_address, 'ftp_port' = ftp_port, 'ftp_login' = ftp_login, 'ftp_password' = ftp_password, 'alt_snapshot_folder' = alt_snapshot_folder, 'working_directory' = working_directory, 'use_ftp' = use_ftp, 'publication_type' = publication_type, 'dts_package_name' = dts_package_name, 'dts_package_location' = dts_package_location, 'offload_agent' = offload_agent, 'offload_server' = offload_server, a.last_sync_status, a.last_sync_summary, 'last_sync_time' = convert(nvarchar(12), a.last_sync_time, 112) + substring(convert(nvarchar(24), a.last_sync_time, 121), 11,13) from MSreplication_subscriptions rs left outer join MSsubscription_properties sp on (UPPER(rs.publisher) = UPPER(sp.publisher) and rs.publisher_db = sp.publisher_db and rs.publication = sp.publication) left outer join MSsubscription_agents a on (UPPER(rs.publisher) = UPPER(a.publisher) and rs.publisher_db = a.publisher_db and ((rs.publication = a.publication and rs.independent_agent = 1 and a.publication <> N'ALL') or (a.publication = N'ALL' and rs.independent_agent = 0)) and rs.subscription_type = a.subscription_type) where ((@publisher = N'%') OR (UPPER(rs.publisher) = UPPER(@publisher))) AND ((@publisher_db = N'%') OR (rs.publisher_db = @publisher_db)) AND ((@publication = N'ALL' AND rs.independent_agent = 0) OR rs.publication LIKE @publication) AND (rs.subscription_type <> @push OR @show_push_bit = 1) ORDER BY rs.publisher, rs.publisher_db, rs.publication GO raiserror('Creating procedure sp_MStable_has_unique_index', 0,1) go create procedure sp_MStable_has_unique_index @tabid int as begin /* ** Returns id of unique index, if it exists, else 0 */ declare @indid int if (ObjectProperty(@tabid, 'IsTable') = 1) and (ObjectProperty(@tabid, 'TableHasIndex') = 1) begin -- First get the primary index id. select @indid = i.indid from sysindexes i where -- get the primary key index (i.status & 2048) <> 0 and i.id = @tabid if @indid is null begin -- Get the first unique index select top 1 @indid = i.indid from sysindexes i where (i.status & 2) <> 0 and i.id = @tabid order by i.indid asc end if @indid is null select @indid = 0 end else select @indid = 0 return @indid end go raiserror('Creating procedure sp_MSchange_retention', 0,1) GO CREATE PROCEDURE sp_MSchange_retention (@pubid uniqueidentifier, @value nvarchar(255)) as declare @re_pubid uniqueidentifier declare @artid uniqueidentifier declare @schemaversion int declare @schemaguid uniqueidentifier declare @schematype int declare @schematext nvarchar(2000) declare @retcode int -- Security check if 1 <> {fn ISPALUSER(@pubid)} begin raiserror(15247,-1,-1) return 1 end begin TRAN update sysmergepublications set retention = convert(int, @value) where pubid = @pubid if @@ERROR<>0 goto UNDO declare #change_retention CURSOR LOCAL FAST_FORWARD fast_forward for select pubid from sysmergearticles where pubid<>@pubid and nickname in (select nickname from sysmergearticles where pubid=@pubid) open #change_retention fetch #change_retention into @re_pubid while (@@fetch_status <> -1) BEGIN update sysmergepublications set retention = convert(int, @value) where pubid = @re_pubid if @@ERROR<>0 goto UNDO set @schematype = 9 /* change retention */ set @artid = newid() select @schematext = 'exec dbo.sp_MSchange_retention '+ '''' + convert(nchar(36),@re_pubid) + '''' + ',' + '''' + @value + '''' select @schemaversion = schemaversion from sysmergeschemachange if (@schemaversion is NULL) set @schemaversion = 1 else select @schemaversion = 1 + max(schemaversion) from sysmergeschemachange set @schemaguid = newid() exec @retcode=sp_MSinsertschemachange @re_pubid, @artid, @schemaversion, @schemaguid, @schematype, @schematext if @@ERROR<>0 or @retcode<>0 goto UNDO fetch #change_retention into @re_pubid END close #change_retention deallocate #change_retention COMMIT TRAN return (0) UNDO: if @@TRANCOUNT = 1 ROLLBACK TRAN else COMMIT TRAN return(1) GO exec dbo.sp_MS_marksystemobject sp_MSchange_retention go grant execute on dbo.sp_MSchange_retention to public raiserror('Creating procedure sp_MSchange_priority', 0,1) GO -- @value has to be unicode too. CREATE PROCEDURE sp_MSchange_priority (@subid uniqueidentifier, @value nvarchar(255)) as declare @retcode int exec @retcode = dbo.sp_MSreplcheck_subscribe if @retcode <> 0 or @@error <> 0 return 1 update sysmergesubscriptions set priority = convert(real, @value) where subid = @subid go exec dbo.sp_MS_marksystemobject sp_MSchange_priority go grant execute on dbo.sp_MSchange_priority to public raiserror('Creating procedure sp_expired_subscription_cleanup', 0,1) GO CREATE PROCEDURE sp_expired_subscription_cleanup AS declare @retcode int declare @publisher_db sysname declare @category int declare @proc_name nvarchar(200) declare @distributor sysname declare @distribdb sysname declare @distproc nvarchar(300) /* ** Security Check */ EXEC @retcode = dbo.sp_MSreplcheck_publish IF @@ERROR <> 0 or @retcode <> 0 return (1) /* ** Get distribution server information for remote RPC call. */ EXECUTE @retcode = sp_helpdistributor @rpcsrvname = @distributor OUTPUT, @distribdb = @distribdb OUTPUT IF @@ERROR <> 0 or @retcode <> 0 BEGIN RAISERROR (20036, 16, -1) return (1) END DECLARE DC CURSOR LOCAL FAST_FORWARD for select DISTINCT name, category from master..sysdatabases where (category & 4) = 4 or (category & 1 = 1) for read only open DC fetch DC into @publisher_db, @category WHILE (@@fetch_status <> -1) BEGIN if (@category & 4 = 4) begin select @proc_name = @publisher_db + '.dbo.sp_MSdrop_expired_mergesubscription' exec @retcode = @proc_name if @retcode<>0 or @@ERROR<>0 goto DONE end if (@category & 1 = 1) begin select @proc_name = @publisher_db + '.dbo.sp_MSdrop_expired_subscription' exec @retcode = @proc_name if @retcode<>0 or @@ERROR<>0 goto DONE end fetch DC into @publisher_db, @category END /* ** sp_MScleanup_agent_entry in distribution database is called to periodically remove obselete ** entries in MSmerge_agents, which may be caused by the following reasons: ** 1. publishing database is externally removed; therefore cleanup agent can not do its job ** 2. Entries for anonymous merge subscriptions */ SELECT @distproc = RTRIM(@distributor) + '.' + RTRIM(@distribdb) + '..sp_MScleanup_agent_entry' exec @retcode = @distproc if @@ERROR<>0 or @retcode<>0 BEGIN close DC deallocate DC return (1) END DONE: close DC deallocate DC GO go exec dbo.sp_MS_marksystemobject sp_expired_subscription_cleanup go grant execute on dbo.sp_expired_subscription_cleanup to public raiserror('Creating procedure sp_addmergepullsubscription', 0,1) GO CREATE PROCEDURE sp_addmergepullsubscription ( @publication sysname, /* Publication name */ @publisher sysname = @@SERVERNAME, /* Publisher server */ @publisher_db sysname = NULL, /* Publication database */ @subscriber_type nvarchar(15) = 'local', /* Subscriber type */ @subscription_priority real = NULL, /* Subscription priority */ @sync_type nvarchar(15) = 'automatic', /* subscription sync type */ @description nvarchar(255) = NULL ) AS SET NOCOUNT ON /* ** Declarations. */ declare @retcode int declare @subscriber_db sysname declare @subnickname int declare @subscriber_srvid int declare @publisher_srvid int declare @priority real declare @subid uniqueidentifier declare @subscriber_typeid smallint declare @subscription_type smallint declare @command nvarchar(255) declare @inactive tinyint declare @global tinyint /* subscriber type is global */ declare @push tinyint /* subscription type is push */ declare @sync_typeid tinyint declare @nosync tinyint declare @automatic tinyint declare @pubid uniqueidentifier declare @partnerid uniqueidentifier declare @parentid uniqueidentifier /* ** Initializations. */ SET @nosync = 2 /* Const: synchronization type 'none' */ SET @automatic = 1 /* Const: synchronization type 'automatic' */ SET @inactive = 0 SET @global = 1 SET @push = 0 set @pubid = newid() set @partnerid = @pubid set @parentid = '00000000-0000-0000-0000-000000000000' /* ** Check if replication components are installed on this server */ exec @retcode = dbo.sp_MS_replication_installed if (@retcode <> 1) begin return (1) end /* ** Security Check. */ EXEC @retcode = dbo.sp_MSreplcheck_subscribe if @@ERROR <> 0 or @retcode <> 0 return(1) /* ** Check to see if merge system tables exist. Create them unless they already ** exist. */ IF not exists (select name from sysobjects where name='sysmergesubscriptions') BEGIN execute @retcode = dbo.sp_MScreate_mergesystables if @@ERROR <> 0 or @retcode <> 0 begin return (1) end END if UPPER(@publisher) = UPPER(@@SERVERNAME) and @publisher_db = db_name() begin raiserror(21126, 16, -1) return (1) end if exists (select pubid from sysmergepublications where UPPER(publisher) = UPPER(@@SERVERNAME) and publisher_db=db_name()) and @subscriber_type in ('local', 'anonymous') begin declare @dbname sysname select @dbname = DB_NAME() raiserror(21258, 16, -1, @dbname) return (1) end /* ** When adding a pull subscription, if a push subscription for that publication already exists, ** we will raise error and fail */ IF EXISTS (select name from sysmergepublications where name = @publication and UPPER(publisher)=UPPER(@publisher) and publisher_db=@publisher_db) BEGIN select @pubid=pubid from sysmergepublications where name = @publication and UPPER(publisher)=UPPER(@publisher) and publisher_db=@publisher_db IF EXISTS (select subid from sysmergesubscriptions where pubid=@pubid and subid<>@pubid and subscription_type=0) begin RAISERROR (21317, 16, -1, @publication) return (1) end ELSE begin IF EXISTS (select status from sysmergesubscriptions where pubid=@pubid and status = 2) begin select @subid = subid from sysmergesubscriptions where pubid=@pubid and subid<>pubid delete sysmergesubscriptions where pubid=@pubid delete MSmerge_replinfo where repid = @subid end ELSE begin RAISERROR (14058, 16, -1) return (1) end end END set @partnerid = @pubid /* ** Assign parameter values appropriately for the local server database */ set @subscriber_db = DB_NAME() select @subscriber_srvid = 0 /* ** Parameter Check: @publisher ** Check to make sure that the publisher is defined */ IF @publisher IS NULL BEGIN RAISERROR (14043, 16, -1, '@publisher') RETURN (1) END IF LOWER(@publisher) = 'all' BEGIN RAISERROR (14136, 16, -1) RETURN (1) END EXECUTE @retcode = dbo.sp_validname @publisher IF @@ERROR <> 0 OR @retcode <> 0 RETURN (1) /* ** Validate that the publisher is a valid server */ select @publisher_srvid = srvid from master..sysservers where UPPER(srvname) = UPPER(@publisher) collate database_default IF @publisher_srvid IS NULL BEGIN EXECUTE @retcode = dbo.sp_addserver @publisher IF @@error <> 0 OR @retcode <> 0 BEGIN RAISERROR (14010, 16, -1) RETURN (1) END ELSE select @publisher_srvid = srvid from master..sysservers where UPPER(srvname) = UPPER(@publisher) collate database_default END /* ** Parameter Check: @publisher_db */ IF @publisher_db IS NULL BEGIN RAISERROR (14043, 16, -1, '@publisher_db') RETURN (1) END IF LOWER(@publisher_db) = 'all' BEGIN RAISERROR (14136, 16, -1) RETURN (1) END /* ** Check to see if the publication name is already used in the subscription ** database - This is the case where we are resubscribing to the same publication. ** Execute dbo.sp_MSpublicationcleanup to cleanup all all the defunct rows ** if exists (select * from sysmergepublications where name = @publication) ** begin ** exec @retcode = dbo.sp_MSpublicationcleanup ** IF @@ERROR <> 0 OR @retcode <> 0 ** BEGIN ** RAISERROR (20025, 16, -1, @publication) ** RETURN (1) ** END ** end */ /* ** Parameter Check: @subscriber_type. ** Set subscriber_typeid based on the @subscriber_type specified. ** ** subscriber_type subscriber_type ** ================= =============== ** 1 global ** 2 local ** 3 anonymous ** NO support for republisher for B 3 */ if LOWER(@subscriber_type collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('local', 'global', 'anonymous') BEGIN RAISERROR (20023, 16, -1) RETURN (1) END set @subscription_type = 1 /* pull by default */ if LOWER(@subscriber_type collate SQL_Latin1_General_CP1_CS_AS) IN ('global') set @subscriber_typeid = 1 else if LOWER(@subscriber_type collate SQL_Latin1_General_CP1_CS_AS) IN ('local') set @subscriber_typeid = 2 else if LOWER(@subscriber_type collate SQL_Latin1_General_CP1_CS_AS) IN ('anonymous') begin /* For anonymous subscribers set subscription type appropriately */ set @subscriber_typeid = 3 set @subscription_type = 2 end /* ** Assign priority appropriately - choose 0.99 times the minimum priority ** of the global replicas. */ if (@subscription_priority > 100.0 or @subscription_priority < 0.0) set @subscription_priority = NULL if (@subscription_priority IS NULL) begin select @priority = 0.99 * min(priority) from sysmergesubscriptions where subscriber_type = 1 /* global/loopback */ if (@priority IS NOT NULL) select @subscription_priority = @priority if (@subscription_priority IS NULL) select @subscription_priority = 0.0 end /* ** For local and anonymous subscriptions the priority is 0.0 */ if LOWER(@subscriber_type collate SQL_Latin1_General_CP1_CS_AS) IN ('local', 'anonymous') select @subscription_priority = 0.0 /* ** If the subscription already exists, don't add it. ** if EXISTS (select db_name, srvid ** FROM sysmergesubscriptions ** WHERE db_name = @subscriber_db ** AND srvid = @subscriber_srvid ** AND pubid = @pubid) ** BEGIN ** RAISERROR (14058, 16, -1) ** RETURN (1) ** END */ /* ** Parameter Check: @sync_type. ** Set sync_typeid based on the @sync_type specified. ** ** sync_typeid sync_type ** =========== ========= ** 1 automatic ** 2 none */ IF LOWER(@sync_type collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('automatic', 'none') BEGIN RAISERROR (14052, 16, -1) RETURN (1) END IF LOWER(@sync_type collate SQL_Latin1_General_CP1_CS_AS) = 'automatic' BEGIN SET @sync_typeid = @automatic END ELSE BEGIN SET @sync_typeid = @nosync END /* ** UNDONE: Validate that the publisher is of type 'republisher' */ begin tran save TRAN addmergepullsubscription /* Generate a guid for the Subscriber ID */ set @subid = newid() /* Look for existing nickname from any other subscription */ exec dbo.sp_MSgetreplnick NULL, NULL , NULL, @subnickname out if (@@error <> 0) begin goto FAILURE end /* Generate a new replica nickname from the @subid */ if (@subnickname is null) EXECUTE dbo.sp_MSgenreplnickname @subid, @subnickname output /* ** Check to see if MSsubscription_properties table exists. ** If not, create it. */ exec @retcode = dbo.sp_MScreate_sub_tables @tran_sub_table = 0, @property_table = 1, @sqlqueue_table = 0 IF @@ERROR <> 0 or @retcode <> 0 goto FAILURE /* ** The subscription doesn't exist, so let's add it to sysmergesubscriptions */ INSERT sysmergesubscriptions (subid, partnerid, datasource_type, srvid, db_name, pubid, status, subscriber_type, subscription_type, priority, sync_type, description, login_name, subscriber_server, publication) VALUES (@subid, @partnerid, 0, @subscriber_srvid, @subscriber_db, @pubid, @inactive, @subscriber_typeid, @subscription_type, /* for a pull/anon subscription */ @subscription_priority, @sync_typeid, @description, suser_sname(suser_sid()), @@servername, @publication) if @@ERROR <> 0 BEGIN GOTO FAILURE END /* Add a self-subscribed subscription to represent the publication */ insert sysmergepublications(publisher, publisher_db, pubid, name, parentid) values(@publisher, @publisher_db, @pubid, @publication, @parentid) if @@ERROR <> 0 begin goto FAILURE end insert sysmergesubscriptions(subid, partnerid, datasource_type, srvid, db_name, pubid, subscriber_type, subscription_type, status, priority, sync_type, description, login_name, subscriber_server, publication, distributor) values (@pubid, @pubid, 0, @publisher_srvid, @publisher_db, @pubid, @global, @push, @inactive, 100.0, @sync_typeid, @description, suser_sname(suser_sid()), @publisher, @publication, @publisher) if @@ERROR <> 0 begin goto FAILURE end /* ** Add row for subscription in MSmerge_replinfo. */ insert MSmerge_replinfo(repid, replnickname) values (@subid, @subnickname) if @@ERROR <> 0 BEGIN GOTO FAILURE END COMMIT TRAN return (0) FAILURE: RAISERROR (14057, 16, -1) if @@trancount > 0 begin ROLLBACK TRANSACTION addmergepullsubscription COMMIT TRANSACTION end RETURN (1) go exec dbo.sp_MS_marksystemobject sp_addmergepullsubscription go grant execute on dbo.sp_addmergepullsubscription to public go raiserror('Creating procedure sp_changemergepullsubscription', 0,1) GO CREATE PROCEDURE sp_changemergepullsubscription ( @publication sysname = '%', /* Publication name */ @publisher sysname = '%', /* Publisher server */ @publisher_db sysname = '%', /* Publication database */ @property sysname = NULL, /* The property to change */ @value nvarchar(255) = NULL /* The new property value */ ) AS SET NOCOUNT ON /* ** Declarations. */ declare @subscriber_srvid int declare @publisher_srvid int declare @retcode int declare @pubid uniqueidentifier declare @subid uniqueidentifier declare @partnerid uniqueidentifier declare @sync_typeid tinyint declare @nosync tinyint declare @automatic tinyint declare @artid uniqueidentifier declare @subscriber sysname declare @subscriber_db sysname declare @schematype int declare @schemaversion int declare @schemaguid uniqueidentifier declare @db_name sysname declare @subscriber_type int declare @schematext nvarchar(2000) declare @use_interactive_bit bit declare @use_interactive_int int declare @enabled_for_syncmgr int declare @regkey nvarchar(1000) declare @snapshot_ready int /* ** Initializations. */ SET @subscriber = @@SERVERNAME SET @subscriber_db = DB_NAME() SET @nosync = 2 /* Const: synchronization type 'none' */ SET @automatic = 1 /* Const: synchronization type 'automatic' */ select @subscriber_srvid = srvid from master..sysservers where UPPER(srvname) = UPPER(@subscriber) collate database_default IF @subscriber_srvid IS NULL BEGIN RAISERROR (14010, 16, -1) RETURN (1) END /* ** Security Check. */ BEGIN exec @retcode = dbo.sp_MSreplcheck_subscribe if @@ERROR <> 0 or @retcode <> 0 return(1) END /* ** Check to see if current database is enabled for subscribing */ IF not exists (select name from sysobjects where name='sysmergesubscriptions') BEGIN RAISERROR (14055, 16, -1) RETURN (1) END /* ** Parameter Check: @property. ** If the @property parameter is NULL, print the options. */ IF @property IS NULL BEGIN CREATE TABLE #tab1 (properties sysname collate database_default not null) INSERT INTO #tab1 VALUES ('sync_type') INSERT INTO #tab1 VALUES ('priority') INSERT INTO #tab1 VALUES ('description') INSERT INTO #tab1 VALUES ('use_interactive_resolver') -- Properties delegated to sp_change_subscription_properties INSERT INTO #tab1 VALUES ('publisher_login') INSERT INTO #tab1 VALUES ('publisher_password') INSERT INTO #tab1 VALUES ('publisher_security_mode') INSERT INTO #tab1 VALUES ('distributor') INSERT INTO #tab1 VALUES ('distributor_login') INSERT INTO #tab1 VALUES ('distributor_password') INSERT INTO #tab1 VALUES ('distributor_security_mode') INSERT INTO #tab1 VALUES ('ftp_address') INSERT INTO #tab1 VALUES ('ftp_port') INSERT INTO #tab1 VALUES ('ftp_login') INSERT INTO #tab1 VALUES ('ftp_password') INSERT INTO #tab1 VALUES ('alt_snapshot_folder') INSERT INTO #tab1 VALUES ('working_directory') INSERT INTO #tab1 VALUES ('use_ftp') INSERT INTO #tab1 VALUES ('offload_agent') INSERT INTO #tab1 VALUES ('offload_server') INSERT INTO #tab1 VALUES ('dynamic_snapshot_location') select * FROM #tab1 RETURN (0) END /* ** Parameter Check: @publisher. ** Check to make sure we have a valid publisher. ** Should make sure that @publisher is non-null before using it to check whether @publication is valid */ IF @publisher IS NULL BEGIN RAISERROR (14043, 16, -1, '@publisher') RETURN (1) END /* ** Parameter Check: @publication. ** Make sure that the publication exists. */ IF @publication IS NULL BEGIN RAISERROR (14043, 16, -1, '@publication') RETURN (1) END select @pubid = pubid FROM sysmergepublications WHERE name = @publication and UPPER(publisher)=UPPER(@publisher) and publisher_db=@publisher_db IF @pubid IS NULL BEGIN RAISERROR (20026, 11, -1, @publication) RETURN (1) END /* ** Validate that the publisher is a valid server */ select @publisher_srvid = srvid from master..sysservers where UPPER(srvname) = UPPER(@publisher) collate database_default IF @publisher_srvid IS NULL BEGIN RAISERROR (14010, 16, -1) RETURN (1) END /* ** Check to see if you have a local / global subscription on this publication */ set @subid = NULL select @subid = subs1.subid, @pubid = pubs.pubid, /* identified from publication name */ @subscriber_type=subs1.subscriber_type, @partnerid = subs2.subid from sysmergesubscriptions subs1, sysmergesubscriptions subs2, sysmergepublications pubs where subs1.srvid = @subscriber_srvid and subs1.db_name = @subscriber_db and subs2.srvid = @publisher_srvid and subs2.db_name = @publisher_db and subs1.pubid = subs2.subid and subs2.pubid = pubs.pubid and pubs.name = @publication and UPPER(pubs.publisher)=UPPER(@publisher) and pubs.publisher_db = @publisher_db if @subid IS NULL begin RAISERROR (14050, 11, -1) RETURN(1) end /* ** Parameter Check: @property. ** Check to make sure that @property is a valid property in ** a merge pull subscription. */ IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('sync_type', 'priority', 'description', 'publisher_login', 'publisher_password', 'publisher_security_mode', 'distributor', 'distributor_login', 'distributor_password', 'distributor_security_mode', 'ftp_address', 'ftp_port', 'ftp_login', 'ftp_password', 'alt_snapshot_folder', 'working_directory', 'use_ftp', 'use_interactive_resolver', 'offload_agent', 'offload_server', 'dynamic_snapshot_location') BEGIN RAISERROR (21348, 16, -1, @property) RETURN (1) END /* ** Change the property. */ IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'sync_type' BEGIN /* ** Check to make sure that we have a valid sync_type. */ IF LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('automatic', 'none') BEGIN RAISERROR (14052, 16, -1) RETURN (1) END /* ** Determine the integer value for the sync_type. */ IF LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) = 'automatic' SET @sync_typeid = @automatic ELSE SET @sync_typeid = @nosync /* ** Update the subscription with the new sync_type. */ UPDATE sysmergesubscriptions SET sync_type = @sync_typeid WHERE subid = @subid IF @@ERROR <> 0 BEGIN RAISERROR (14053, 16, -1) RETURN (1) END END IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'description' BEGIN UPDATE sysmergesubscriptions SET description = @value WHERE subid = @subid IF @@ERROR <> 0 BEGIN RAISERROR (14053, 16, -1) RETURN (1) END END IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'use_interactive_resolver' BEGIN /* Check to make sure that we have a true/false. */ IF LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('true', 'false') BEGIN RAISERROR (14148, 16, -1, 'use_interactive_resolver') RETURN (1) END /* Determine the bit value. */ IF LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) = 'true' SET @use_interactive_bit = 1 ELSE SET @use_interactive_bit = 0 /* Update the subscription with the new 'use_interactive' value. */ UPDATE sysmergesubscriptions SET use_interactive_resolver = @use_interactive_bit WHERE subid = @subid IF @@ERROR <> 0 BEGIN RAISERROR (14053, 16, -1) RETURN (1) END /* If the subscription is enable for Sync Manager, then update the reg value */ exec sp_MSsubscription_enabled_for_syncmgr @publisher, @publisher_db, @publication, @subscriber, @subscriber_db, @enabled_for_syncmgr OUT, @regkey OUT IF @@ERROR <> 0 BEGIN RAISERROR (14053, 16, -1) RETURN (1) END if @enabled_for_syncmgr = 1 begin select @use_interactive_int = convert(int, @use_interactive_bit) EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE', @regkey, 'UseInteractiveResolver', 'REG_DWORD', @use_interactive_int if @retcode <> 0 OR @@ERROR <> 0 BEGIN RAISERROR (14053, 16, -1) RETURN (1) END end END IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'priority' BEGIN select @db_name = db_name from sysmergesubscriptions where (pubid=@pubid) and (subid=@pubid) IF @db_name <> db_name() BEGIN RAISERROR (20047, 16, -1) RETURN (1) END /* Only the original publisher can change priority of a global subscriptions */ IF @subscriber_type<>1 BEGIN RAISERROR (20044, 16, -1) /* Local subscriber does not have priority*/ RETURN (1) END BEGIN TRANSACTION save tran sp_changemergepullsubscription exec dbo.sp_MSchange_priority @subid, @value select @snapshot_ready=snapshot_ready from sysmergepublications where pubid = @pubid /* Insert the sp_MSchange_priority schema change only if the publication's snapshot is ready */ if (@snapshot_ready > 0) begin select @schemaversion = schemaversion from sysmergeschemachange if (@schemaversion is NULL) set @schemaversion = 1 else select @schemaversion = 1 + max(schemaversion) from sysmergeschemachange set @schemaguid = newid() set @artid = newid() set @schematype = 8 /* change priority */ select @schematext = 'exec dbo.sp_MSchange_priority '+ '''' + convert(nchar(36),@subid) + '''' + ',' + '''' + @value + '''' exec dbo.sp_MSinsertschemachange @pubid, @artid, @schemaversion, @schemaguid, @schematype, @schematext if @@ERROR <> 0 goto Rollback_tran end COMMIT TRANSACTION END IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) IN ('publisher_login', 'publisher_password', 'publisher_security_mode', 'distributor', 'distributor_login', 'distributor_password', 'distributor_security_mode', 'ftp_address', 'ftp_port', 'ftp_login', 'ftp_password', 'alt_snapshot_folder', 'working_directory', 'use_ftp', 'offload_agent', 'offload_server', 'dynamic_snapshot_location') BEGIN EXEC @retcode = sp_change_subscription_properties @publisher = @publisher, @publisher_db = @publisher_db, @publication = @publication, @property = @property, @value = @value, @publication_type = 2 IF @retcode <> 0 RETURN 1 END /* ** Return succeed. */ RAISERROR (14054, 10, -1) RETURN (0) Rollback_tran: rollback tran sp_changemergepullsubscription commit tran return(1) go exec dbo.sp_MS_marksystemobject sp_changemergepullsubscription go grant execute on dbo.sp_changemergepullsubscription to public go raiserror('Creating procedure sp_helpmergepullsubscription', 0,1) GO CREATE PROCEDURE sp_helpmergepullsubscription( @publication sysname = '%', /* Publication name */ @publisher sysname = '%', /* Publisher server */ @publisher_db sysname = '%', /* Publication database */ @subscription_type nvarchar(10) = 'pull' /* Show only pull subscriptions */ )AS SET NOCOUNT ON /* ** Declarations. */ declare @retcode int declare @srvid int declare @pubid uniqueidentifier declare @subid uniqueidentifier declare @partnerid uniqueidentifier declare @cursor_open int declare @subscriber sysname declare @subscriber_db sysname declare @subscription_set nvarchar(10) declare @publisher_local sysname declare @publisher_db_local sysname declare @publication_local sysname declare @subscription_name nvarchar(1000) declare @regkey nvarchar(1000) declare @syncmgr_keyexist int declare @helpsubscriptioncursor_open int /* ** Initializations. */ set @cursor_open = 0 select @publisher_db = RTRIM(@publisher_db) select @publication = RTRIM(@publication) -- For attach if exists (select * from sysobjects where name = 'MSrepl_restore_stage') -- The database is attached from a subscription copy file without using -- sp_attachsubscription. Return nothing return 0 /* ** Calling sp_help* is all right whether current database is enabled for pub/sub or not */ IF not exists (select * from sysobjects where name='sysmergesubscriptions') RETURN (0) /* Security check */ EXEC @retcode = dbo.sp_MSreplcheck_subscribe if @@ERROR <> 0 or @retcode <> 0 return(1) set @subscriber = @@SERVERNAME set @subscriber_db = DB_NAME() /* ** Parameter Check: @publisher ** Check to make sure that the publisher is defined */ IF @publisher <> '%' AND @publisher IS NOT NULL BEGIN EXECUTE @retcode = dbo.sp_validname @publisher IF @@ERROR <> 0 OR @retcode <> 0 RETURN (1) END /* ** Parameter Check: @publication. ** If the publication name is specified, check to make sure that it ** conforms to the rules for identifiers and that the publication ** actually exists. Disallow NULL. */ if @publication IS NULL BEGIN RAISERROR (14043, 16, -1, '@publication') RETURN (1) END /* ** Parameter Check: @subscription_type. ** Set subscription_typeid based on the @subscription_type specified. ** ** subscription_type subscription_type ** ================= =============== ** 0 push ** 1 pull ** 0,1 both */ if LOWER(@subscription_type collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('push', 'pull', 'both') BEGIN RAISERROR (14128, 16, -1) RETURN (1) END IF LOWER(@subscription_type collate SQL_Latin1_General_CP1_CS_AS) = 'both' set @subscription_set = '(0, 1)' else IF LOWER(@subscription_type collate SQL_Latin1_General_CP1_CS_AS) = 'push' set @subscription_set = '(0)' else set @subscription_set = '(1,2)' -- including pull subscription and pull/anonymous subscription IF NOT EXISTS (SELECT * FROM sysobjects WHERE type = 'U' AND name = 'MSsubscription_properties') RETURN (0) /* ** Get subscriptions */ create table #helpmergepullsubscription ( publication sysname collate database_default not null, publisher sysname collate database_default not null, publisher_db sysname collate database_default not null, subscriber sysname collate database_default not null, subscriber_db sysname collate database_default not null, status int NOT NULL, subscriber_type int NOT NULL, subscription_type int NOT NULL, priority float(8) NOT NULL, sync_type tinyint NOT NULL, description nvarchar(255) collate database_default null, merge_jobid binary(16) NULL, enabled_for_syncmgr int NULL, last_updated nvarchar(26) collate database_default null, use_interactive_resolver int NULL, subid uniqueidentifier not NULL, last_sync_status int NULL, last_sync_summary sysname collate database_default null ) IF @publisher IS NULL and @publisher_db IS NULL BEGIN select @subid = subid from sysmergesubscriptions where subid = partnerid set @partnerid = @subid -- show the loopback subscription insert into #helpmergepullsubscription select pubs.name, servers2.srvname, subs2.db_name, servers1.srvname, subs1.db_name, subs1.status, subs1.subscriber_type, subs1.subscription_type, subs1.priority, subs1.sync_type, subs1.description, replinfo.merge_jobid, 0, convert(nvarchar(12), subs1.last_sync_date, 112) + substring(convert(nvarchar(24), subs1.last_sync_date, 121), 11,13), subs1.use_interactive_resolver, @subid, subs1.last_sync_status, subs1.last_sync_summary FROM sysmergesubscriptions subs1, sysmergesubscriptions subs2, MSmerge_replinfo replinfo, master.dbo.sysservers servers1, master.dbo.sysservers servers2, sysmergepublications pubs where subs1.subid = @subid and subs2.subid = @partnerid and pubs.pubid = subs1.pubid and servers1.srvid = subs1.srvid and servers2.srvid = subs2.srvid and subs1.subid = subs1.partnerid and replinfo.repid = subs1.subid END else begin declare #cursor cursor local FAST_FORWARD FOR select DISTINCT sub.subid, sub.partnerid FROM sysmergesubscriptions sub, sysmergesubscriptions sub1, master.dbo.sysservers ss, master.dbo.sysservers ss1, sysmergepublications pub WHERE ((@subscriber = N'%') OR (UPPER(ss.srvname) = UPPER(@subscriber) collate database_default)) AND ((@publisher = N'%') OR (UPPER(ss1.srvname) = UPPER(@publisher) collate database_default)) AND sub1.srvid = ss1.srvid AND sub.srvid = ss.srvid AND pub.name LIKE @publication AND sub.pubid = pub.pubid AND ((@subscriber_db = N'%') OR (sub.db_name = @subscriber_db collate database_default)) AND ((@publisher_db = N'%') OR (sub1.db_name = @publisher_db collate database_default)) AND sub1.pubid = pub.pubid AND (sub.subscription_type=1 or sub.subscription_type=2) FOR READ ONLY open #cursor select @cursor_open = 1 fetch next from #cursor into @subid, @partnerid while (@@fetch_status <> -1) begin insert into #helpmergepullsubscription select pubs.name, servers2.srvname, subs2.db_name, servers1.srvname, subs1.db_name, subs1.status, subs1.subscriber_type, subs1.subscription_type, subs1.priority, subs1.sync_type, subs1.description, replinfo.merge_jobid, 0, convert(nvarchar(12), subs1.last_sync_date, 112) + substring(convert(nvarchar(24), subs1.last_sync_date, 121), 11,13), subs1.use_interactive_resolver, @subid, subs1.last_sync_status, subs1.last_sync_summary FROM sysmergesubscriptions subs1, sysmergesubscriptions subs2, MSmerge_replinfo replinfo, master.dbo.sysservers servers1, master.dbo.sysservers servers2, sysmergepublications pubs where subs1.subid = @subid and subs2.subid = @partnerid and pubs.pubid = subs1.pubid and servers1.srvid = subs1.srvid and servers2.srvid = subs2.srvid and @subid <> @partnerid -- do not show the loopback subscription and replinfo.repid = subs1.subid if @@ERROR <> 0 begin set @retcode = 1 goto DONE end fetch next from #cursor into @subid, @partnerid end end declare #helpsubscriptioncursor CURSOR LOCAL FAST_FORWARD FOR select DISTINCT publisher, publisher_db, publication FROM #helpmergepullsubscription FOR READ ONLY create table #syncmgr_keyexist (syncmgr_keyexist int) open #helpsubscriptioncursor select @helpsubscriptioncursor_open = 1 fetch next from #helpsubscriptioncursor into @publisher_local, @publisher_db_local, @publication_local while (@@fetch_status <> -1) begin set @subscription_name = @publisher_local + ':' + @publisher_db_local + ':' + @publication_local + ':' + @subscriber + ':' + @subscriber_db /* Replace back slash with forward slash so that the key name is a valid REGISTRY key name */ set @subscription_name = REPLACE(@subscription_name,'\','/') set @regkey = 'SOFTWARE\Microsoft\Microsoft SQL Server\80\Replication\Subscriptions\' + @subscription_name insert into #syncmgr_keyexist EXECUTE master.dbo.xp_regread 'HKEY_LOCAL_MACHINE', @regkey select @syncmgr_keyexist = syncmgr_keyexist from #syncmgr_keyexist update #helpmergepullsubscription set enabled_for_syncmgr = @syncmgr_keyexist where UPPER(publisher) = UPPER(@publisher_local) and publisher_db = @publisher_db_local and publication = @publication_local fetch next from #helpsubscriptioncursor into @publisher_local, @publisher_db_local, @publication_local end select 'subscription_name'= hs.publisher + ':' + hs.publisher_db + ':' + hs.publication collate database_default, hs.publication, hs.publisher, hs.publisher_db, hs.subscriber, hs.subscriber_db, hs.status, hs.subscriber_type, hs.subscription_type, hs.priority, hs.sync_type, hs.description, hs.merge_jobid, hs.enabled_for_syncmgr, hs.last_updated, sp.publisher_login, sp.publisher_password, sp.publisher_security_mode, sp.distributor, sp.distributor_login, sp.distributor_password, sp.distributor_security_mode, 'ftp_address' = null, 'ftp_port' = 0, 'ftp_login' = null, 'ftp_password' = null, sp.alt_snapshot_folder, sp.working_directory, sp.use_ftp, sp.offload_agent, sp.offload_server, hs.use_interactive_resolver, hs.subid, sp.dynamic_snapshot_location, hs.last_sync_status, hs.last_sync_summary from #helpmergepullsubscription hs left outer join MSsubscription_properties sp on hs.publisher = sp.publisher collate database_default and hs.publisher_db = sp.publisher_db collate database_default and hs.publication = sp.publication collate database_default order by hs.publisher, hs.publisher_db, hs.publication, hs.subscriber, hs.subscriber_db select @retcode = 0 DONE: if (@cursor_open = 1) begin close #cursor deallocate #cursor end --drop table #helpmergepullsubscription return @retcode go exec dbo.sp_MS_marksystemobject sp_helpmergepullsubscription go grant execute on dbo.sp_helpmergepullsubscription to public go raiserror('Creating procedure sp_addmergepullsubscription_agent', 0,1) GO CREATE PROCEDURE sp_addmergepullsubscription_agent ( @name sysname = NULL, @publisher sysname, /* Publisher server */ @publisher_db sysname, /* Publisher database */ @publication sysname, /* Publication name */ @publisher_security_mode int = 1, @publisher_login sysname = NULL, @publisher_password sysname = NULL, @publisher_encrypted_password bit = 0, @subscriber sysname = NULL, @subscriber_db sysname = NULL, @subscriber_security_mode int = NULL, /* 0 standard; 1 integrated */ @subscriber_login sysname = NULL, @subscriber_password sysname = NULL, @distributor sysname = @@SERVERNAME, @distributor_security_mode int = 0, /* 0 standard; 1 integrated */ @distributor_login sysname = 'sa', @distributor_password sysname = NULL, @encrypted_password bit = 0, /* distributor password encrypted or not */ @frequency_type int = NULL, @frequency_interval int = NULL, @frequency_relative_interval int = NULL, @frequency_recurrence_factor int = NULL, @frequency_subday int = NULL, @frequency_subday_interval int = NULL, @active_start_time_of_day int = NULL, @active_end_time_of_day int = NULL, @active_start_date int = NULL, @active_end_date int = NULL, @optional_command_line nvarchar(255) = '', /* Optional command line arguments */ @merge_jobid binary(16) = NULL OUTPUT, @enabled_for_syncmgr nvarchar(5) = 'false', /* Enabled for SYNCMGR: true or false */ @ftp_address sysname = NULL, @ftp_port int = NULL, @ftp_login sysname = NULL, @ftp_password sysname = NULL, @alt_snapshot_folder nvarchar(255) = NULL, @working_directory nvarchar(255) = NULL, @use_ftp nvarchar(5) = 'false', @reserved nvarchar(100) = N'', -- Not default to null because null problems in conditional expressions. @use_interactive_resolver nvarchar(5) = 'false', @offloadagent nvarchar(5) = 'false', @offloadserver sysname = null, -- Used by DMO scripting @job_name sysname = NULL, @dynamic_snapshot_location nvarchar(260) = NULL ) AS SET NOCOUNT ON /* ** Declarations. */ declare @command nvarchar(4000) declare @retcode int declare @database sysname declare @repid uniqueidentifier declare @pubid uniqueidentifier declare @subscriber_srvid int declare @publisher_srvid int declare @name_id nvarchar(50) declare @subscriber_typeid int declare @subscription_type_id int declare @category_name sysname declare @platform_nt binary DECLARE @subscriber_enc_password nvarchar(524) DECLARE @publisher_enc_password nvarchar(524) DECLARE @distributor_enc_password nvarchar(524) DECLARE @use_ftp_bit bit declare @use_interactive_bit bit DECLARE @offload_agent_bit bit select @platform_nt = 0x1 SELECT @use_ftp_bit = 0 /* Security check */ EXEC @retcode = dbo.sp_MSreplcheck_subscribe if @@ERROR <> 0 or @retcode <> 0 return(1) -- For attach check if exists (select * from sysobjects where name = 'MSrepl_restore_stage') begin raiserror(21211, 16, -1) return 1 end -- Set null @optional_command_line to empty string to avoid string concat problem if @optional_command_line is null set @optional_command_line = '' else set @optional_command_line = N' ' + LTRIM( RTRIM(@optional_command_line) ) + N' ' IF @distributor_password = N'' select @distributor_password = NULL IF @publisher_password = N'' select @publisher_password = NULL IF @ftp_password = N'' select @ftp_password = NULL /* ** Parameter Check: @subscriber and @subscriber_db */ if @subscriber IS NULL or rtrim(@subscriber) = '' SELECT @subscriber = @@SERVERNAME if @subscriber_db IS NULL or rtrim(@subscriber_db) = '' SELECT @subscriber_db = DB_NAME() EXECUTE @retcode = dbo.sp_validname @subscriber IF @@ERROR <> 0 OR @retcode <> 0 RETURN (1) EXECUTE @retcode = dbo.sp_validname @subscriber_db IF @@ERROR <> 0 OR @retcode <> 0 RETURN (1) -- Parameter check: @subscriber_security_mode if @subscriber_security_mode is null begin if ( platform() & @platform_nt ) = @platform_nt select @subscriber_security_mode = 1 else select @subscriber_security_mode = 0 end /* ** Parameter check: @alt_snapshot_folder ** @alt_snapshot_folder and @use_ftp are mutually exclusive ** @dynamic_snapshot_location is incompatible with both ** @alt_snapshot_folder and @use_ftp */ IF @alt_snapshot_folder <> N'' AND @alt_snapshot_folder IS NOT NULL BEGIN IF LOWER(@use_ftp collate SQL_Latin1_General_CP1_CS_AS) = N'true' BEGIN RAISERROR(21146, 16, -1) RETURN (1) END IF @dynamic_snapshot_location <> N'' AND @dynamic_snapshot_location IS NOT NULL BEGIN RAISERROR(21341, 16, -1) RETURN (1) END END /* ** Parameter Check: @use_interactive_resolver */ if LOWER(@use_interactive_resolver collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('true', 'false') BEGIN RAISERROR (14148, 16, -1, '@use_interactive_resolver') RETURN (1) END if LOWER(@use_interactive_resolver collate SQL_Latin1_General_CP1_CS_AS) = 'true' set @use_interactive_bit = 1 else set @use_interactive_bit = 0 /* ** Parameter check: @use_ftp ** Must be 'true' or 'false' */ IF LOWER(@use_ftp collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('true', 'false') BEGIN RAISERROR (14148, 16, -1, '@use_ftp') RETURN (1) END IF LOWER(@use_ftp collate SQL_Latin1_General_CP1_CS_AS) = 'true' BEGIN /* ** Ftp file transfer is incompatible with @dynamic_snapshot_location */ IF @dynamic_snapshot_location <> N'' AND @dynamic_snapshot_location IS NOT NULL BEGIN RAISERROR (21342, 16, -1) RETURN (1) END SELECT @use_ftp_bit = 1 END ELSE BEGIN SELECT @use_ftp_bit = 0 END /* ** Parameter Check: @offloadserver ** If @offloadagent = 'true' then @offloadserver cannot be null */ SELECT @offloadagent = LOWER(@offloadagent collate SQL_Latin1_General_CP1_CS_AS) IF @offloadagent NOT IN ('true', 'false') BEGIN RAISERROR (14148, 16, -1, '@offloadagent') RETURN (1) END IF @offloadagent = 'true' BEGIN SELECT @offload_agent_bit = 1 END ELSE BEGIN SELECT @offload_agent_bit = 0 END IF @offload_agent_bit = 1 AND (@offloadserver IS NULL or @offloadserver = N'') BEGIN RAISERROR(21215, 16, -1) RETURN (1) END IF UPPER(@offloadserver) = UPPER(@@SERVERNAME) AND @offload_agent_bit = 1 BEGIN RAISERROR(21227, 16, -1) RETURN (1) END EXEC @retcode = sp_MSreplcheckoffloadserver @offloadserver IF @retcode <> 0 OR @@ERROR <> 0 RETURN (1) -- Make sure that there are no leading or trailing blanks -- in the dynamic snapshot location select @dynamic_snapshot_location = rtrim(ltrim(@dynamic_snapshot_location)) if ( ( platform() & @platform_nt ) <> @platform_nt and @subscriber_security_mode = 1) begin RAISERROR(21038, 16, -1) RETURN (1) end select @subscription_type_id = 1 /* pull agent only */ /* ** Set Default schedule values if NULL is specified ** The default are not implemented during parmeter defintion because this procedure ** is can be called from sp_addmergesubscription. */ if @frequency_type is NULL set @frequency_type = 4 /* Daily */ if @frequency_interval is NULL set @frequency_interval = 1 if @frequency_relative_interval is NULL set @frequency_relative_interval = 1 if @frequency_recurrence_factor is NULL set @frequency_recurrence_factor = 0 if @frequency_subday is NULL set @frequency_subday = 8 /* Hour */ if @frequency_subday_interval is NULL set @frequency_subday_interval = 1 if @active_start_time_of_day is NULL set @active_start_time_of_day = 0 if @active_end_time_of_day is NULL set @active_end_time_of_day = 235959 if @active_start_date is NULL set @active_start_date = 0 if @active_end_date is NULL set @active_end_date = 99991231 select @subscriber_srvid = srvid from master..sysservers where UPPER(srvname) = UPPER(@@SERVERNAME) collate database_default IF @subscriber_srvid IS NULL BEGIN RAISERROR (14010, 16, -1) RETURN (1) END select @pubid = pubid from sysmergepublications where name = @publication and UPPER(publisher)=UPPER(@publisher) and publisher_db=@publisher_db IF @pubid is NULL begin RAISERROR (20026, 16, -1, @publication) RETURN (1) end select @repid = subid, @subscriber_typeid = subscriber_type from sysmergesubscriptions where srvid = @subscriber_srvid and pubid<>subid and pubid = @pubid and db_name = @subscriber_db if @subscriber_typeid = 3 set @subscription_type_id = 2 /* This corresponds to anonymous subscription */ if (@subscription_type_id <> 0) begin if (@subscriber_security_mode = 0) and (@subscriber_login IS NULL or rtrim(@subscriber_login) = '') begin raiserror(3217, 16, -1, '@subscriber_login') return (1) end end if (@distributor_security_mode = 0) and (@distributor_login IS NULL or rtrim(@distributor_login) = '') begin raiserror(3217, 16, -1, '@distributor_login') return (1) end if (@publisher_security_mode = 0) and (@publisher_login IS NULL or rtrim(@publisher_login) = '') begin raiserror(3217, 16, -1, '@publisher_login') return (1) end IF NOT EXISTS (select * from sysobjects where name = 'MSsubscription_properties' and type = 'U') begin raiserror(14027, 16, -1, 'The subscription properties table ''MSsubscription_properties''') return (1) end declare @job_existing bit -- For scripting if @job_name is null select @job_existing = 0 else begin select @job_existing = 1 select @name = @job_name end /* ** Construct unique task name if @name = NULL */ IF @name IS NULL begin SELECT @name = CONVERT(nvarchar(23),@publisher ) + '-' + CONVERT(nvarchar(23),@publisher_db) + '-' + CONVERT(nvarchar(23),@publication) + '-' + CONVERT(nvarchar(23),@subscriber) + '-' + CONVERT(nvarchar(23), @subscriber_db) + '- 0' end else begin /* ** validate name */ exec @retcode = dbo.sp_MSreplcheck_name @name if @@ERROR <> 0 or @retcode <> 0 return(1) end -- Get property values. if @reserved = 'no_change_to_properties' begin -- Get the distributor value. It will be used in agent command line. select @distributor = distributor, @enabled_for_syncmgr = case enabled_for_syncmgr when 0 then 'false' when 1 then 'true' end from MSsubscription_properties where UPPER(publisher) = UPPER(@publisher) and publisher_db = @publisher_db and publication = @publication end begin tran save tran sp_addpullsub_agent if @job_existing = 0 begin /* Construct task command */ select @command = '-Publisher ' + QUOTENAME(@publisher) + ' -PublisherDB ' + QUOTENAME(@publisher_db) + ' ' select @command = @command + '-Publication ' + QUOTENAME(@publication) + ' ' select @command = @command + '-Subscriber ' + QUOTENAME(@@SERVERNAME) + ' ' select @command = @command + '-SubscriberDB ' + QUOTENAME(db_name()) + ' ' SELECT @command = @command + '-SubscriptionType ' + convert(nvarchar(10), @subscription_type_id) + ' ' select @command = @command + '-SubscriberSecurityMode ' + convert(nvarchar(10),@subscriber_security_mode) + ' ' if @subscriber_login is not NULL select @command = @command + '-SubscriberLogin ' + quotename(@subscriber_login) + ' ' if @subscriber_password is not NULL begin set @subscriber_enc_password = @subscriber_password exec @retcode = master.dbo.xp_repl_encrypt @subscriber_enc_password OUTPUT select @command = @command + '-SubscriberEncryptedPassword ' + quotename(@subscriber_enc_password) + ' ' end select @command = @command + @optional_command_line select @command = @command + ' -Distributor ' + QUOTENAME(@distributor) + ' ' if @offload_agent_bit = 1 select @command = @command + N'-Offload ' + @offloadserver + N' ' select @dynamic_snapshot_location = rtrim(ltrim(@dynamic_snapshot_location)) if @dynamic_snapshot_location is not null and @dynamic_snapshot_location <> N'' select @command = @command + N'-DynamicSnapshotLocation ' + fn_replquotename(@dynamic_snapshot_location) collate database_default + N' ' select @database = db_name() -- Get Merge category name (assumes category_id = 14) select @category_name = name FROM msdb.dbo.syscategories where category_id = 14 EXEC @retcode = dbo.sp_MSadd_repl_job @name = @name, @subsystem = 'Merge', @server = @@SERVERNAME, @databasename = @database, @enabled = 1, @freqtype = @frequency_type, @freqinterval = @frequency_interval, @freqsubtype = @frequency_subday, @freqsubinterval = @frequency_subday_interval, @freqrelativeinterval = @frequency_relative_interval, @freqrecurrencefactor = @frequency_recurrence_factor, @activestartdate = @active_start_date, @activeenddate = @active_end_date, @activestarttimeofday = @active_start_time_of_day, @activeendtimeofday = @active_end_time_of_day, @command = @command, @retryattempts = 10, @retrydelay = 1, @category_name = @category_name, @job_id = @merge_jobid OUTPUT if @@ERROR <> 0 or @retcode <> 0 goto Rollback_tran end else begin select @merge_jobid = job_id from msdb..sysjobs_view where name = @name collate database_default and UPPER(originating_server) = UPPER(CONVERT(sysname, SERVERPROPERTY('ServerName'))) if @merge_jobid IS NULL begin -- Message from msdb.dbo.sp_verify_job_identifiers RAISERROR(14262, -1, -1, 'Job', @name) goto Rollback_tran end end if @reserved <> 'attach_subscription' and (@subscription_type_id = 1) OR (@subscription_type_id = 2) begin IF NOT EXISTS (select * from MSsubscription_properties where UPPER(publisher) = UPPER(@publisher) and publisher_db = @publisher_db and publication = @publication) BEGIN -- Copy the passwords to new value before attempting to encrypt set @distributor_enc_password = @distributor_password set @publisher_enc_password = @publisher_password IF (@encrypted_password = 0) -- Encrypt the password BEGIN EXEC @retcode = master.dbo.xp_repl_encrypt @distributor_enc_password OUTPUT IF @@error <> 0 OR @retcode <> 0 goto Rollback_tran END IF (@publisher_encrypted_password = 0) -- Encrypt the password BEGIN EXEC @retcode = master.dbo.xp_repl_encrypt @publisher_enc_password OUTPUT IF @@error <> 0 OR @retcode <> 0 goto Rollback_tran END INSERT INTO MSsubscription_properties (publisher, publisher_db, publication, publication_type, publisher_login,publisher_password, publisher_security_mode, distributor, distributor_login, distributor_password, distributor_security_mode, ftp_address, ftp_port, ftp_login, ftp_password, alt_snapshot_folder, working_directory, use_ftp, offload_agent, offload_server, dynamic_snapshot_location) values (@publisher, @publisher_db, @publication, 2, @publisher_login, @publisher_enc_password, @publisher_security_mode, @distributor, @distributor_login, @distributor_enc_password, @distributor_security_mode, null, null, null, null, @alt_snapshot_folder, @working_directory, @use_ftp_bit, @offload_agent_bit, @offloadserver, @dynamic_snapshot_location) END end /* Update merge joibd for this pull subscription */ UPDATE MSmerge_replinfo set merge_jobid = @merge_jobid WHERE repid = @repid /* Update the distributor column in sysmergesubscriptions */ UPDATE sysmergesubscriptions set use_interactive_resolver = @use_interactive_bit, distributor = @distributor WHERE subid = @repid /* Conditional support for MobileSync */ if LOWER(@enabled_for_syncmgr collate SQL_Latin1_General_CP1_CS_AS) = 'true' BEGIN /* Call sp_MSregistersubscription so that the subscription can be synchronized via MobileSync etc. */ exec @retcode = dbo.sp_MSregistersubscription @replication_type = 2, @publisher = @publisher, @publisher_security_mode = @publisher_security_mode, @publisher_login = @publisher_login, @publisher_password = @publisher_password, @publisher_db = @publisher_db, @publication = @publication, @subscriber = @subscriber, @subscriber_db = @subscriber_db, @subscriber_security_mode = @subscriber_security_mode, @subscriber_login = @subscriber_login, @subscriber_password = @subscriber_password, @distributor = @distributor, @distributor_security_mode = @distributor_security_mode, @distributor_login = @distributor_login, @distributor_password = @distributor_password, @subscription_id = @repid, @subscription_type = @subscription_type_id, @use_interactive_resolver = @use_interactive_bit IF @@ERROR <> 0 or @retcode <> 0 goto Rollback_tran END commit tran RETURN (0) Rollback_tran: rollback tran sp_addpullsub_agent commit tran return(1) GO exec dbo.sp_MS_marksystemobject sp_addmergepullsubscription_agent go raiserror('Creating procedure sp_MSget_mergepullsubsagent_owner', 0,1) GO CREATE PROCEDURE sp_MSget_mergepullsubsagent_owner( @publication sysname = NULL, /* Publication name */ @publisher sysname = NULL, /* Publisher server */ @publisher_db sysname = NULL, /* Publication database */ @owner_sid varbinary(85) OUTPUT )AS declare @srvid int declare @pubid uniqueidentifier declare @subid uniqueidentifier declare @job_id uniqueidentifier set nocount on select @owner_sid = NULL if exists (select * from sysobjects where type = 'U' and name = 'sysmergesubscriptions') -- Get the server id of the current server (subscriber) begin -- Get the srvid of the current subscriber database select @srvid = srvid from master.dbo.sysservers where upper(@@servername) = upper(srvname) collate database_default -- Get the pubid from sysmergepublications using @publisher, -- @publisher_db, @publication select @pubid = pubid from sysmergepublications where @publication = name -- Get the subid from sysmergesubscriptions using @pubid and @srvid select @subid = subid from sysmergesubscriptions where @pubid = pubid and @srvid = srvid and pubid <> subid -- Get the merge_jobid from MSreplication_info using @subid select @job_id = merge_jobid from MSmerge_replinfo where @subid = repid -- Finally, get the owner_sid from msdb..sysjobs using @job_id select @owner_sid = owner_sid from msdb..sysjobs where @job_id = job_id end go exec dbo.sp_MS_marksystemobject 'sp_MSget_mergepullsubsagent_owner' raiserror('Creating procedure sp_dropmergepullsubscription', 0,1) GO CREATE PROCEDURE sp_dropmergepullsubscription( @publication sysname = NULL, /* Publication name */ @publisher sysname = NULL, /* Publisher server */ @publisher_db sysname = NULL, /* Publication database */ @reserved bit = 0 )AS SET NOCOUNT ON /* ** Declarations. */ declare @retcode int declare @subscriber_srvid int declare @publisher_srvid int declare @pubid uniqueidentifier declare @subid uniqueidentifier declare @partnerid uniqueidentifier declare @local_server sysname declare @local_db sysname declare @merge_jobid binary(16) declare @cmd nvarchar(255) declare @pubidstr nvarchar(38) declare @subscriber sysname declare @subscriber_db sysname declare @subscriber_type int declare @local_job bit declare @implicit_transaction int declare @close_cursor_at_commit int declare @owner_sid varbinary(85) declare @owner_name sysname declare @qualified_publication_name nvarchar(512) select @close_cursor_at_commit = 0 select @implicit_transaction = 0 /* ** Get original setting values before setting them to false for recursive calling */ IF (@reserved = 0) BEGIN SELECT @implicit_transaction = @@options & 2 SELECT @close_cursor_at_commit = @@options & 4 SET IMPLICIT_TRANSACTIONS OFF SET CURSOR_CLOSE_ON_COMMIT OFF END /* ** Security Check. */ exec @retcode = dbo.sp_MSreplcheck_subscribe if @@ERROR <> 0 or @retcode <> 0 return(1) /* ** Initializations. */ set @local_db = DB_NAME() set @local_server = @@SERVERNAME set @subscriber = @@SERVERNAME set @subscriber_db = DB_NAME() /* ** Assign parameter values appropriately */ select @subscriber_srvid = srvid from master..sysservers where UPPER(srvname) = UPPER(@subscriber) collate database_default IF @subscriber_srvid IS NULL BEGIN RAISERROR (14010, 16, -1) RETURN (1) END IF not exists (select name from sysobjects where name='sysmergesubscriptions') BEGIN RAISERROR (14055, 16, -1) RETURN (1) END /* ** Parameter Check: @publisher ** Check to make sure that the publisher is defined */ IF @publisher IS NULL BEGIN RAISERROR (14043, 16, -1, '@publisher') RETURN (1) END EXECUTE @retcode = dbo.sp_validname @publisher IF @@ERROR <> 0 OR @retcode <> 0 RETURN (1) /* ** Parameter Check: @publisher_db */ IF @publisher_db IS NULL BEGIN RAISERROR (14043, 16, -1, '@publisher_db') RETURN (1) END /* ** Parameter Check: @publication. ** If the publication name is specified, check to make sure that it ** conforms to the rules for identifiers and that the publication ** actually exists. Disallow NULL. */ if @publication IS NULL BEGIN RAISERROR (14043, 16, -1, '@publication') RETURN (1) END IF LOWER(@publication) = 'all' BEGIN declare hC1 CURSOR LOCAL FAST_FORWARD FOR select DISTINCT name FROM sysmergepublications FOR READ ONLY OPEN hC1 FETCH hC1 INTO @publication if @@fetch_status = -1 begin CLOSE hC1 DEALLOCATE hC1 RETURN (0) --- It's OK to have no publication when 'ALL' end WHILE (@@fetch_status <> -1) BEGIN EXECUTE dbo.sp_dropmergepullsubscription @publication = @publication, @publisher = @publisher, @publisher_db = @publisher_db, @reserved = 1 FETCH hC1 INTO @publication END CLOSE hC1 DEALLOCATE hC1 RETURN (0) END IF LOWER(@publisher) = 'all' BEGIN declare hC4 CURSOR LOCAL FAST_FORWARD FOR select DISTINCT srvname FROM master..sysservers FOR READ ONLY OPEN hC4 FETCH hC4 INTO @publisher WHILE (@@fetch_status <> -1) BEGIN EXECUTE dbo.sp_dropmergepullsubscription @publication = @publication, @publisher = @publisher, @publisher_db = @publisher_db, @reserved = 1 FETCH hC4 INTO @publisher END CLOSE hC4 DEALLOCATE hC4 RETURN (0) END /* ** Validate that the publisher is a valid server */ select @publisher_srvid = srvid from master..sysservers where UPPER(srvname) = UPPER(@publisher) collate database_default IF @publisher_srvid IS NULL BEGIN --RAISERROR (14010, 16, -1) RETURN (1) END /* Previously the condition is set as 'AND subid<>pubid' which is fatally errorous */ IF LOWER(@publisher_db) = 'all' BEGIN declare hC5 CURSOR LOCAL FAST_FORWARD FOR select DISTINCT db_name FROM sysmergesubscriptions WHERE subid = pubid and pubid in (select pubid from sysmergepublications where UPPER(publisher)=UPPER(@publisher) and name=@publication) FOR READ ONLY OPEN hC5 FETCH hC5 INTO @publisher_db WHILE (@@fetch_status <> -1) BEGIN EXECUTE dbo.sp_dropmergepullsubscription @publication = @publication, @publisher = @publisher, @publisher_db = @publisher_db, @reserved = 1 FETCH hC5 INTO @publisher_db END CLOSE hC5 DEALLOCATE hC5 RETURN (0) END /* ** return error if only there is no 'ALL'. Same is true for the rest of error handling. */ if NOT EXISTS (select * FROM sysmergepublications WHERE name = @publication and UPPER(publisher)=UPPER(@publisher) and publisher_db=@publisher_db) BEGIN if @reserved = 0 RAISERROR (20026, 16, -1, @publication) RETURN (1) END select @pubid = pubid from sysmergepublications where name = @publication and UPPER(publisher)=UPPER(@publisher) and publisher_db=@publisher_db set @pubidstr = '''' + convert(nchar(36), @pubid) + '''' if @pubid is null BEGIN if @reserved = 0 RAISERROR (20026, 16, -1, @publication) RETURN (1) END /* ** Only members of the sysadmin group and the creator of the distribution ** agent can drop a pull subscription successfully. This behavior matches ** the behavior of the sysjobs_view. DBO of the subscriber database, ** sysadmins (owner is undefined) can drop a subscription if the owner_sid ** is null. */ EXEC sp_MSget_mergepullsubsagent_owner @publisher = @publisher, @publisher_db = @publisher_db, @publication = @publication, @owner_sid = @owner_sid OUTPUT IF (@owner_sid is not null AND (SUSER_SID() <> @owner_sid) AND (ISNULL(IS_SRVROLEMEMBER('sysadmin'),0) = 0)) BEGIN SELECT @owner_name = SUSER_SNAME(@owner_sid) SELECT @qualified_publication_name = @publisher + N':' + @publisher_db + N':' + @publication RAISERROR(21121,16,-1,@owner_name, @qualified_publication_name) RETURN (1) END /* ** Get subscriptions from either local replicas or global replicas */ select @subid = subs1.subid, @subscriber_type = subs1.subscriber_type, @partnerid = subs2.subid from sysmergesubscriptions subs1, sysmergesubscriptions subs2, sysmergepublications pubs where subs1.srvid = @subscriber_srvid and subs1.db_name = @subscriber_db and subs2.srvid = @publisher_srvid and subs2.db_name = @publisher_db and subs1.pubid = subs2.subid and subs2.pubid = pubs.pubid and pubs.name = @publication and UPPER(pubs.publisher)=UPPER(@publisher) and pubs.publisher_db=@publisher_db if @subid IS NULL begin if @reserved = 0 raiserror (14050, 16, -1) RETURN (0) end begin tran save TRAN dropmergepullsubscription /* ** Drop the local merge task */ select @merge_jobid = merge_jobid from MSmerge_replinfo WHERE repid = @subid if (@merge_jobid IS NOT NULL) BEGIN IF EXISTS (SELECT * FROM msdb..sysjobs_view WHERE job_id = @merge_jobid) BEGIN -- Checks if the job name matches one that is generated -- by replication EXEC @retcode = dbo.sp_MSispullmergejobnamegenerated @publisher = @publisher, @publisher_db = @publisher_db, @publication = @publication, @job_id = @merge_jobid IF @@ERROR <> 0 GOTO FAILURE -- Only drop the job if the name was generated IF @retcode = 0 BEGIN EXEC @retcode = msdb.dbo.sp_delete_job @job_id = @merge_jobid IF @@ERROR <> 0 or @retcode <> 0 GOTO FAILURE END END END if @subid <> @partnerid BEGIN DELETE MSmerge_replinfo WHERE repid = @subid IF @@ERROR <> 0 GOTO FAILURE delete from sysmergesubscriptions where subid = @subid if @@ERROR <> 0 GOTO FAILURE /* Call sp_MSunregistersubscription so that the reg entries get deleted */ exec @retcode = dbo.sp_MSunregistersubscription @publisher = @publisher, @publisher_db = @publisher_db, @publication = @publication, @subscriber = @@SERVERNAME, @subscriber_db = @subscriber_db IF @retcode<>0 or @@ERROR<>0 GOTO FAILURE exec dbo.sp_MSpublicationcleanup @publisher=@publisher, @publisher_db = @publisher_db, @publication = @publication IF @@ERROR <> 0 BEGIN RAISERROR (20025, 16, -1, @publication) GOTO FAILURE END END IF EXISTS(select * from sysobjects where type='U' and name = 'MSsubscription_properties') BEGIN DELETE FROM MSsubscription_properties WHERE UPPER(publisher) = UPPER(@publisher) AND publisher_db = @publisher_db AND publication = @publication IF @@ERROR <> 0 GOTO FAILURE IF NOT EXISTS (SELECT * FROM MSsubscription_properties) BEGIN exec @retcode = dbo.sp_MSsub_cleanup_prop_table IF @@ERROR <> 0 or @retcode <> 0 GOTO FAILURE END END COMMIT TRAN /* ** Set back original settings */ IF @reserved = 0 BEGIN /* ** If last subscription is dropped and the DB is not enabled for publishing, ** then remove the merge system tables */ IF (not exists (select * from sysmergesubscriptions )) AND (select category & 4 FROM master..sysdatabases WHERE name = DB_NAME())=0 BEGIN execute @retcode = dbo.sp_MSdrop_mergesystables if @@ERROR <> 0 or @retcode <> 0 begin return (1) end END IF @implicit_transaction <>0 SET IMPLICIT_TRANSACTIONS ON IF @close_cursor_at_commit <>0 SET CURSOR_CLOSE_ON_COMMIT ON END RETURN(0) FAILURE: RAISERROR (14056, 16, -1) if @@trancount > 0 begin ROLLBACK TRANSACTION dropmergepullsubscription COMMIT TRANSACTION end /* ** Set back original settings */ IF @reserved = 0 BEGIN IF @implicit_transaction <>0 SET IMPLICIT_TRANSACTIONS ON IF @close_cursor_at_commit <>0 SET CURSOR_CLOSE_ON_COMMIT ON END return 1 go exec dbo.sp_MS_marksystemobject sp_dropmergepullsubscription go grant execute on dbo.sp_dropmergepullsubscription to public go -- synctran supporting sprocs raiserror('Creating procedure sp_MSreplraiserror', 0,1) go create proc sp_MSreplraiserror @errorid int, @param1 sysname = null, @param2 sysname= null as if @errorid = 20508 raiserror (20508, 16, 1) else if @errorid = 20509 raiserror (20509, 16, 1) else if @errorid = 20510 raiserror (20510, 16, 1) else if @errorid = 20511 raiserror (20511, 16, 1) else if @errorid = 20512 raiserror (20512, 16, 1) else if @errorid = 20515 raiserror (20515, 16, 1) else if @errorid = 20516 raiserror (20516, 16, 1) else if @errorid = 20517 raiserror (20517, 16, 1) else if @errorid = 20518 raiserror (20518, 16, 1) else if @errorid = 20519 raiserror (20519, 16, 1) else if @errorid = 20520 raiserror (20520, 16, 1) else if @errorid = 21034 raiserror (21034, 16, 1) else if @errorid = 21052 raiserror (21052, 16, 1) else if @errorid = 21054 raiserror (21054, 16, 1) else if @errorid = 21064 raiserror (21064, 16, 1) else if @errorid = 21161 raiserror (21161, 16, 1) else if @errorid = 20598 raiserror (20598, 16, 1) go exec dbo.sp_MS_marksystemobject sp_MSreplraiserror go -- -- Name: sp_check_sync_trigger -- -- Description: This SP is used by insert sync trigger on subscriber to check the trigger nesting level. -- The SP returns 1 if the trigger nestlevel is > 0. Else it returns 0. -- -- Parameter: Refer to the comments in the create procedure statement -- -- Returns: 1 = there is a nesting in the synctran trigger, 0 = no nesting -- -1 = Error -- -- Security: Public procedure - Internal security check. -- raiserror('Creating procedure sp_check_sync_trigger', 0,1) go create proc sp_check_sync_trigger ( @trigger_procid int ,@trigger_op char(10) OUTPUT ,@owner sysname = null ) as begin declare @trigid int -- -- Security check -- Make sure this proc is infact being called from the given object(trigger) -- if (trigger_nestlevel(@trigger_procid) = 0) begin raiserror(14126, 16, 2) return -1 end -- -- Security check: the caller of this SP has to be one of the -- predefined replication triggers defined in the db -- if (@owner is null) begin if (@trigger_procid not in (select object_id(object_name) from dbo.MSreplication_objects where object_type = 'T')) begin raiserror(14126, 16, 3) return -1 end end else begin if (@trigger_procid not in (select object_id(quotename(@owner) + N'.' + quotename(object_name)) from dbo.MSreplication_objects where object_type = 'T')) begin raiserror(14126, 16, 3) return -1 end end -- -- process -- select @trigger_op = NULL select @trigid = so1.id from sysobjects so1, sysobjects so2 where so1.type = N'TR' and so1.name like N'trg_MSsync_ins_%' and so1.parent_obj = so2.parent_obj and so2.id = @trigger_procid -- if nestlevel of insert trigger on same table > 0 then bail if trigger_nestlevel( @trigid ) > 0 return 1 else return 0 end go exec dbo.sp_MS_marksystemobject sp_check_sync_trigger go -- -- Name: sp_check_for_sync_trigger -- -- Description: This procedure determines if sync tran trigger is -- being called in the context of an updatable subscription. This -- stored procedure is executed at the Subscriber on the subscription database. -- -- Parameter: Refer to the comments in the create procedure statement -- -- Returns: 1 or 0 0 = success -- -- Security: Public procedure - does subscribe security check. -- NOTE : Is this really used by customers ? -- raiserror('Creating procedure sp_check_for_sync_trigger', 0,1) go create proc sp_check_for_sync_trigger ( @tabid int, @trigger_op char(10) = NULL OUTPUT ) as begin declare @ins_trigid int declare @upd_trigid int declare @del_trigid int declare @retcode int -- -- security check -- exec @retcode = sp_MSreplcheck_subscribe if @@error <> 0 or @retcode <> 0 begin return (1) end select @trigger_op = NULL select @ins_trigid = id from sysobjects where type = N'TR' and name like N'trg_MSsync_ins_%' and parent_obj = @tabid select @upd_trigid = id from sysobjects where type = N'TR' and name like N'trg_MSsync_upd_%' and parent_obj = @tabid select @del_trigid = id from sysobjects where type = N'TR' and name like N'trg_MSsync_del_%' and parent_obj = @tabid if trigger_nestlevel( @ins_trigid ) > 0 begin select @trigger_op = 'ins' return 1 end else -- if nestlevel of insert trigger on same table > 0 then bail if trigger_nestlevel( @upd_trigid ) > 0 begin select @trigger_op = 'upd' return 1 end else if trigger_nestlevel( @del_trigid ) > 0 begin select @trigger_op = 'del' return 1 end else return 0 end go exec dbo.sp_MS_marksystemobject sp_check_for_sync_trigger go raiserror('Creating procedure sp_MSpad_command', 0,1) go create proc sp_MSpad_command ( @cmd nvarchar(4000) output, @indent int = 0) -- indent for command buffer (for pretty formatting as BEGIN declare @cnt int ,@num_tabs int ,@num_spaces int select @cmd = N'' select @num_tabs = @indent / 4 select @num_spaces = @indent % 4 select @cnt = 0 while (@cnt < @num_tabs) begin select @cmd = @cmd + N' ' select @cnt = @cnt + 1 end select @cnt = 0 while (@cnt < @num_spaces) begin select @cmd = @cmd + N' ' select @cnt = @cnt + 1 end END go raiserror('Creating procedure sp_MSflush_command', 0,1) go create proc sp_MSflush_command @cmd nvarchar(4000) output, @force int, -- 0 = flush if necesssary, 1 = flush always @indent int = 0 -- indent for command buffer (for pretty formatting as -- debug -- if len(@cmd) >= 4000 -- begin -- raiserror("buffer overflow!", 16, 1) -- select @cmd -- end -- debug if @force = 1 or len( @cmd ) > 3000 begin insert into #proctext(procedure_text) values( @cmd ) select @cmd = N'' if @indent > 0 exec dbo.sp_MSpad_command @cmd output, @indent end go raiserror('Creating procedure sp_MSget_colinfo', 0,1) go create proc sp_MSget_colinfo @objid int, @colid int, @columns binary(32), @bGetTextImageInfo tinyint = 0, -- boolean for returning text/image info @colname sysname output, @ccoltype sysname = null output as declare @isset int if @columns is not NULL -- this code path for synctran procs exec @isset = dbo.sp_isarticlecolbitset @colid, @columns else -- this code path for synctran triggers select @isset = 1 if @isset != 0 begin select @colname = c.name, @ccoltype= t.name from syscolumns c, systypes t where id = @objid and colid = @colid and c.xtype = t.xusertype -- when checking replicated columns, text/image datatypes cannot be declared or used locally if (@bGetTextImageInfo = 0) and (@ccoltype in (N'text',N'ntext',N'image')) return 1 end else begin select @colname = null, @ccoltype = null return 1 end return 0 go raiserror('Creating procedure sp_MSget_col_position ', 0,1) go create procedure sp_MSget_col_position ( @objid int, @columns binary(32), -- should be NULL if processing trigger generation @key sysname, @colpos sysname = NULL output, @art_col int = NULL output, @get_num_col bit = 0, @num_col int = NULL output, @this_col int = null output ) as BEGIN declare @colname sysname ,@ccoltype sysname ,@rc int select @num_col = 0 -- -- Use a cursor to walk through the columns -- DECLARE #hCColid CURSOR LOCAL FAST_FORWARD FOR select colid, name from syscolumns where id = @objid order by colid asc OPEN #hCColid FETCH #hCColid INTO @this_col, @colname WHILE (@@fetch_status <> -1) begin if @columns is NULL begin -- -- processing updating trigger generation on subscriber. -- all columns are to be processed -- select @rc = 1 end else begin -- -- processing updating procedure generation on publisher. -- only replicated columns are to be processed -- exec @rc = dbo.sp_isarticlecolbitset @this_col, @columns end if @rc = 1 begin select @num_col = @num_col + 1 -- If @get_num_col is 1, we just need the number of columns in the partition. if (@get_num_col != 1) and (@colname = @key) begin select @colpos = 'c' + convert(varchar(4), @this_col) ,@art_col = @num_col break end end FETCH #hCColid INTO @this_col, @colname end close #hCColid deallocate #hCColid return 0 END go exec dbo.sp_MS_marksystemobject sp_MSget_col_position go raiserror('Creating procedure sp_MSget_map_position ', 0,1) go create procedure sp_MSget_map_position @primary_key_bitmap varbinary(4000) = null, @index int, @colpos sysname = NULL output, @art_col int = NULL output as declare @this_col int declare @num_keys int declare @num_cols int select @this_col = 1 select @num_keys = 0 select @num_cols = datalength(@primary_key_bitmap) * 8 select @colpos = null select @art_col = null while @this_col <= @num_cols begin if (substring(@primary_key_bitmap, 1 + (@this_col-1) / 8 , 1) & power(2, (@this_col-1) % 8 )) <> 0 begin select @num_keys = @num_keys + 1 if @num_keys = @index begin select @art_col = @this_col select @colpos = 'c' + convert(sysname, @this_col) break end end select @this_col = @this_col + 1 end go exec dbo.sp_MS_marksystemobject sp_MSget_map_position go raiserror('Creating procedure sp_MSget_type', 0,1) go create proc sp_MSget_type @tabid int, @colid int, @colname sysname output, @typestring nvarchar(4000) output as declare @ccolchar nvarchar(5) declare @coltype tinyint declare @prec smallint declare @scale int declare @ccoltype sysname declare @xtype int select @colname = c.name, @xtype = c.xtype, @prec = c.prec, @scale = c.scale, @ccoltype = t.name from syscolumns c, systypes t where c.id = @tabid and c.colid = @colid and c.xtype = t.xusertype select @typestring = @ccoltype -- datatypes requiring precision (nchar, nvarchar, binary, varbinary) -- format: @var <dt> (prec) if @ccoltype in (N'char',N'nchar', N'varchar', N'nvarchar', N'binary', N'varbinary') select @typestring = @typestring + N'(' + rtrim(convert(nchar(10),@prec)) + N')' -- datatypes requiring precision & scale (numeric & decimal) -- format: @var <dt> (prec, scale) else if @ccoltype in (N'numeric', N'decimal') select @typestring = @typestring + N'(' + rtrim(convert(nchar(10),ColumnProperty(@tabid, @colname, 'PRECISION'))) + N',' + rtrim(convert(nchar(10),@scale)) + N')' -- text/image datatypes cannot be declared or used locally else if @ccoltype in (N'text',N'ntext',N'image') select @typestring = NULL go raiserror('Creating procedure sp_MSscript_where_clause', 0,1) go create procedure sp_MSscript_where_clause ( @objid int, @columns binary(32), @clause_type varchar(15) = 'pk_new', -- 'new pk', 'old pk', 'upd version', 'upd rc', 'trg pk', 'qcft_comp', 'new_pk_q', 'subwins_check' @ts_col sysname = NULL, @indent int = 0, @op_type char(3) = NULL, -- 'ins', 'del', 'upd' @primary_key_bitmap varbinary(4000) = null ) as BEGIN declare @cmd nvarchar(4000) ,@colname sysname ,@ccoltype sysname ,@spacer nvarchar(20) ,@indkey int ,@indid int ,@key sysname ,@rc int ,@this_col int ,@art_col int ,@src_cols int ,@total_col int ,@col sysname ,@qualname nvarchar(512) ,@curparam nvarchar(20) ,@retcode int ,@fcreatedcolmap bit declare @colmap table (relativeorder int identity(1,1), colid int) select @spacer = N' ' ,@cmd = N'' ,@indkey = 1 ,@indid = 0 ,@fcreatedcolmap = 0 exec sp_MSget_qualified_name @objid, @qualname OUTPUT select @src_cols = max(colid) ,@total_col = count(colid) from syscolumns where id = @objid exec dbo.sp_MSpad_command @cmd output, @indent if (@clause_type = 'qcft_comp') select @cmd = @cmd + N' '' where ' else select @cmd = @cmd + N'where' exec dbo.sp_MSflush_command @cmd output, 1, @indent if @clause_type in ('new pk','old pk','upd version','trg pk','version pk','qcft_comp','new_pk_q','subwins_check') begin if @primary_key_bitmap is null begin exec @indid = dbo.sp_MStable_has_unique_index @objid if @indid is null begin raiserror('Debug: Cannot find unique index', 16, -1) return (1) end end -- -- check if column Id match relative column order -- for specific trigger operations -- if ((@total_col < @src_cols) and (@clause_type = 'trg pk') and (@columns is null) and (@primary_key_bitmap is not null)) begin -- -- this table may have altered columns, so when we need to -- set a mapping for using the bitmaps properly as the bitmap -- always refers relative column order -- insert into @colmap (colid) select colid from syscolumns where id = @objid order by colid if (@@error != 0) begin raiserror('Could not create column mapping', 16, -1) return (1) end select @fcreatedcolmap = 1 end while (1=1) begin -- -- get the column position -- if @primary_key_bitmap is null begin select @key = index_col(@qualname, @indid, @indkey) if @key is null break --exec dbo.sp_MSget_col_position @objid, @columns, @key, @col output, @this_col output exec dbo.sp_MSget_col_position @objid, @columns, @key, @col output, NULL, 0, NULL, @this_col output end else begin exec dbo.sp_MSget_map_position @primary_key_bitmap, @indkey, @col output, @this_col output if @this_col is null break -- -- set the actual column id for this relative order in the PK bitmap if necessary -- if (@fcreatedcolmap = 1) begin select @this_col = colid ,@col = 'c' + convert(sysname, colid) from @colmap where relativeorder = @this_col end end -- -- Get column name -- exec @retcode = dbo.sp_MSget_colinfo @objid, @this_col, @columns, 0, @key output, @ccoltype output if (@retcode = 1) begin -- -- this column not used for replication -- continue -- select @indkey = @indkey + 1 continue end if @clause_type = 'new pk' begin if ColumnProperty(@objid, @key, 'IsIdentity') = 1 select @cmd = @cmd + @spacer + quotename(@key) + N' = @@identity' else select @cmd = @cmd + @spacer + quotename(@key) + N' = @' + @col select @spacer = ' and ' end else if @clause_type in ('upd version', 'subwins_check') begin select @cmd = @cmd + @spacer + quotename(@key) + N' = @' + @col + N'_old' select @spacer = ' and ' end else if @clause_type = 'version pk' begin select @cmd = @cmd + @spacer + @qualname + '.' + quotename(@key) + N' = inserted.' + quotename(@key) select @spacer = ' and ' end else if @clause_type in ('trg pk', 'old pk') begin if @op_type = 'ins' select @cmd = @cmd + @spacer + quotename(@key) + N' = @' + @col + N'_old' else -- The vars correspoding to pk were set in sp_MSscript -- _pkvar_assignment. select @cmd = @cmd + @spacer + quotename(@key) + N' = @' + @col select @spacer = ' and ' end else if (@clause_type = 'qcft_comp') begin -- -- Conflict compensation generation -- This is a special case - we generate -- and exec string for the WHERE clause -- if (@op_type = 'ins') select @curparam = N'@' + @col else if (@op_type = 'del') select @curparam = N'@' + @col + N'_old' else select @curparam = N'ISNULL(@' + @col + N', @' + @col + N'_old)' select @cmd = @cmd + @spacer + quotename(@key) if (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) = 'varchar') select @cmd = @cmd + N' = '' + '''''''' + master.dbo.fn_MSgensqescstr(' + @curparam + N') collate database_default + '''''''' ' else if (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) = 'nvarchar') select @cmd = @cmd + N' = '' + ''N'''''' + master.dbo.fn_MSgensqescstr(' + @curparam + N') collate database_default + '''''''' ' else if (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) = 'char') select @cmd = @cmd + N' = '' + '''''''' + master.dbo.fn_MSgensqescstr(CAST(RTRIM(' + @curparam + N') as nvarchar)) collate database_default + '''''''' ' else if (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) = 'nchar') select @cmd = @cmd + N' = '' + ''N'''''' + master.dbo.fn_MSgensqescstr(CAST(RTRIM(' + @curparam + N') as nvarchar)) collate database_default + '''''''' ' else if (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) in ('binary','varbinary')) select @cmd = @cmd + N' = '' + master.dbo.fn_varbintohexstr(' + @curparam + N') collate database_default ' else if (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) in ('bit','bigint','int','smallint','tinyint','decimal','numeric')) select @cmd = @cmd + N' = '' + CAST(' + @curparam + N' as nvarchar) ' else if (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) in ('float','real')) select @cmd = @cmd + N' = '' + CONVERT(nvarchar(60),' + @curparam + N', 2) ' else if (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) in ('money','smallmoney')) select @cmd = @cmd + N' = '' + CONVERT(nvarchar(40),' + @curparam + N', 2) ' else if (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) = 'uniqueidentifier') select @cmd = @cmd + N' = '' + '''''''' + CAST(' + @curparam + N' as nvarchar(40)) + '''''''' ' else if (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) in ('datetime','smalldatetime')) select @cmd = @cmd + N' = '' + '''''''' + CONVERT(nvarchar(40), ' + @curparam + N', 112) + N'' '' + CONVERT(nvarchar(40), ' + @curparam + N', 114) + '''''''' ' else if (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) = 'sql_variant') select @cmd = @cmd + N' = '' + master.dbo.fn_sqlvarbasetostr(' + @curparam + N' ) collate database_default ' else select @cmd = @cmd + N' = '' + CAST(' + @curparam + N' as nvarchar) ' select @spacer = ' + '' and ' end else if @clause_type = 'new_pk_q' begin -- -- new value of primary key, ignore identity -- used for scripting in synctran procs -- select @cmd = @cmd + @spacer + quotename(@key) + N' = @' + @col select @spacer = ' and ' end select @indkey = @indkey + 1 -- flush command if necessary exec dbo.sp_MSflush_command @cmd output, 1, @indent end -- end of while loop -- add version col as necessary if ((@clause_type in ('upd version','subwins_check')) and (@ts_col is not null)) begin -- -- @ts_col is version col actually. -- check for special cases for queued processing -- exec dbo.sp_MSget_col_position @objid, @columns, @ts_col, @col output if (@clause_type = 'subwins_check') select @cmd = @cmd + @spacer + @ts_col + N' = @' + @col else select @cmd = @cmd + @spacer + @ts_col + N' = @' + @col + N'_old' -- -- save off command fragment -- exec dbo.sp_MSflush_command @cmd output, 1, @indent end end -- end of if clause_type -- 'upd rc' is used for column value conflict detection. It is no longer used. else if @clause_type = 'upd rc' begin select @this_col = 1, @art_col = 1 while @this_col <= @src_cols begin exec @rc = dbo.sp_MSget_colinfo @objid, @this_col, @columns, 0, @colname output, @ccoltype output if @rc = 0 begin select @cmd = @cmd + @spacer + '(' + @colname + N' = @c' + convert(varchar(4), @this_col) + N'_old or (' select @cmd = @cmd + @colname + ' is null and @c' + convert(varchar(4), @this_col) + N'_old is null)) ' select @spacer = N' and ' exec dbo.sp_MSflush_command @cmd output, 0, @indent end exec dbo.sp_MSflush_command @cmd output, 1, @indent select @this_col = @this_col + 1 end -- save off cmd fragment exec dbo.sp_MSflush_command @cmd output, 1, @indent end END go EXEC dbo.sp_MS_marksystemobject sp_MSscript_where_clause GO raiserror('Creating procedure sp_MSscript_params', 0,1) go create procedure sp_MSscript_params ( @objid int, @columns binary(32), @postfix nvarchar(8) = NULL, @bOutParams tinyint = 0, -- boolean indicating wether or not to declare timestamp/identity params as output params @outvars nvarchar(4000) = NULL output) as BEGIN declare @cmd nvarchar(4000) declare @colname sysname declare @typestring nvarchar(4000) declare @spacer nvarchar(1) declare @spacer2 nvarchar(1) declare @this_col int declare @art_col int declare @isset int declare @pkcolumns binary(32) declare @ispkcol int select @spacer = N' ' select @spacer2 = N' ' select @art_col = 1 select @outvars = null select @cmd = N' ' exec dbo.sp_getarticlepkcolbitmap @objid, @pkcolumns output DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR select colid from syscolumns where id = @objid order by colid asc OPEN hCColid FETCH hCColid INTO @this_col WHILE (@@fetch_status <> -1) begin if @columns is not null exec @isset = dbo.sp_isarticlecolbitset @this_col, @columns else select @isset = 1 exec @ispkcol = dbo.sp_isarticlecolbitset @this_col, @pkcolumns if @isset != 0 and EXISTS (select name from syscolumns where id=@objid and colid=@this_col and (iscomputed<>1 or @ispkcol<>0)) begin exec dbo.sp_MSget_type @objid, @this_col, @colname output, @typestring OUTPUT if (@typestring IS NOT NULL) begin if @postfix is null select @cmd = @cmd + @spacer + N'@c' + convert(varchar(4), @this_col) + N' ' + @typestring else -- old vars select @cmd = @cmd + @spacer + N'@c' + convert(varchar(4), @this_col) + @postfix + N' ' + @typestring -- new vars of type timestamp and identity are declared as output params if @bOutParams = 1 and (@typestring = N'timestamp' or ColumnProperty(@objid, @colname, 'IsIdentity') = 1) begin select @cmd = @cmd + N' output' select @outvars = isnull(@outvars, N'') + @spacer2 + N'@c' + convert(varchar(4), @this_col) + N' = ' + @colname select @spacer2 = N',' end select @spacer = N',' end select @art_col = @art_col + 1 -- flush command if necessary exec dbo.sp_MSflush_command @cmd output, 1, 4 end FETCH hCColid INTO @this_col end CLOSE hCColid DEALLOCATE hCColid END go -- -- proc to generate the other param declarations and -- initial proc declarations and assignments for -- synctran/queued updating procs -- raiserror('Creating procedure sp_MSscript_procbodystart', 0,1) go create procedure sp_MSscript_procbodystart ( @queued_pub bit = 0 ) as BEGIN declare @cmd nvarchar(4000) -- -- script the initial declarations and assignments -- select @cmd = N' ,@execution_mode tinyint = 0) AS BEGIN set nocount on declare @retcode int , @rowcount int , @error int , @reinit int , @cmd nvarchar(4000)' exec dbo.sp_MSflush_command @cmd output, 1 select @cmd = N' declare @immediate tinyint ' if (@queued_pub = 1) begin select @cmd = @cmd + N' , @QFirstPass tinyint , @QPubWins tinyint , @QSubWins tinyint , @QReinit tinyint , @cftcase int ' end exec dbo.sp_MSflush_command @cmd output, 1 select @cmd = N' select @immediate = 0 ' if (@queued_pub = 1) begin select @cmd = @cmd + N' , @QFirstPass = 1 , @QPubWins = 2 , @QSubWins = 3 , @QReinit = 4 ' end exec dbo.sp_MSflush_command @cmd output, 1 return 0 END go EXEC dbo.sp_MS_marksystemobject sp_MSscript_procbodystart GO raiserror('Creating procedure sp_MSscript_begintrig1', 0,1) go create procedure sp_MSscript_begintrig1 ( @trigname sysname ,@objid int ,@procname sysname ,@filter_clause nvarchar(4000) ,@op_type char(3) = 'ins' -- ins, upd, del ,@fisqueued bit = 0 -- 1 = Queued subscription ) as BEGIN declare @cmd nvarchar(4000) ,@start int ,@sub_len int ,@subtableowner sysname ,@qualname nvarchar(512) select @subtableowner = user_name(objectproperty(@objid, N'OwnerId')) exec sp_MSget_qualified_name @objid, @qualname OUTPUT -- construct trigger name select @cmd = N'create trigger ' + QUOTENAME(@trigname) + N' on ' + @qualname + N' for ' select @cmd = case when (@op_type = 'ins') then @cmd + N'insert ' when (@op_type = 'upd') then @cmd + N'update ' when (@op_type = 'del') then @cmd + N'delete ' end select @cmd = @cmd + N'not for replication as ' insert into #proctext(procedure_text) values (@cmd) -- -- declare common local variables -- -- ,@update_mode char(40) -- ,@failover_mode char(10) -- insert into #proctext(procedure_text) values (N' declare @rc int ,@retcode int ,@connect_string nvarchar(2000) ,@rpc_proc nvarchar(4000) ,@rpc_types nvarchar(4000) ,@update_mode_id int ,@bitmap varbinary(4000) ,@version_guid uniqueidentifier ,@trigger_op char(10) ') -- -- queued specific declarations -- insert into #proctext(procedure_text) values (N' ,@failover_mode_id int ,@queue_server sysname ,@queue_id sysname ,@tran_id varchar(255) ,@subscriber sysname ,@subscriber_db sysname ,@partial_cmd bit ,@start_offset int ,@end_offset int ,@vb_buffer varbinary(8000) ,@vb_bufferlen int ') -- script variables used to retrieve data from inserted table if @op_type in ('ins', 'upd') begin insert into #proctext(procedure_text) values(N' declare ') exec dbo.sp_MSscript_params @objid, null, null, 0, null end insert into #proctext(procedure_text) values(N' declare ') exec dbo.sp_MSscript_params @objid, null, '_old', 0, null -- Set @rc, @subscriber and @subscriber_db -- Optimization. Return immediately if no row changed select @cmd = N' select @rc = @@ROWCOUNT, @subscriber = @@SERVERNAME, @subscriber_db = db_name() if @rc = 0 return set nocount on ' insert into #proctext(procedure_text) values(@cmd) -- set column update bitmap for update trigger if @op_type in ('upd') begin declare @num_bytes int ,@i_byte int ,@i_bit tinyint ,@len_before nvarchar(10) ,@len_after nvarchar(10) ,@index1 nvarchar(10) ,@index2 nvarchar(10) ,@this_col int ,@max_col int ,@total_col int -- -- check if the subscriber table was altered for column changes -- select @max_col = max(colid) ,@total_col = count(colid) from syscolumns where id = @objid if (@total_col = @max_col) begin -- -- actual colid and relative column order are same -- insert into #proctext(procedure_text) values(N' select @bitmap = columns_updated() ') end else begin -- -- we need to convert the columns_updated bitmap to -- a bitmap that contains relative column information -- select @cmd = N' select @bitmap = fn_repladjustcolumnmap( ' + cast(@objid as sysname) + N', ' + cast(@total_col as sysname) + N', columns_updated())' insert into #proctext(procedure_text) values(@cmd) select @cmd = N' if (@bitmap is null) begin raiserror(''fn_repladjustcolumnmap could not create column mapping'', 16, 1) goto FAILURE end ' insert into #proctext(procedure_text) values(@cmd) end -- -- Mark the version bit in the bitmap as updated. -- select @cmd = N' ' + '-- set the bit for msrepl_tran_version' insert into #proctext(procedure_text) values(@cmd) -- get actual column id exec dbo.sp_MSget_col_position @objid, null, 'msrepl_tran_version', @this_col = @this_col output if (@total_col < @max_col) begin -- -- this table has altered columns, create a mapping between -- relative column position and actual column id -- declare @colmap table (relativeorder int identity(1,1), colid int) insert into @colmap (colid) select colid from syscolumns where id = @objid order by colid if (@@error != 0) begin raiserror('Could not create column mapping', 16, -1) return (1) end -- -- get the relative column position for msrepl_tran_version -- select @this_col = relativeorder from @colmap where colid = @this_col end select @num_bytes = @total_col / 8 + 1 ,@i_byte = 1 + (@this_col-1) / 8 ,@i_bit = power(2, (@this_col-1) % 8 ) select @len_before = convert(nvarchar(10), @i_byte -1) ,@index1 = convert(nvarchar(10), @i_byte) ,@index2 = convert(nvarchar(10), @i_byte + 1) ,@len_after = convert(nvarchar(10), @num_bytes - @i_byte) select @cmd = N' select @bitmap = substring(@bitmap, 1, ' + @len_before + ') + (convert(binary(1), substring(@bitmap, ' + @index1 + ', 1) | convert(tinyint,' + convert(nvarchar(10), @i_bit) + '))) + substring(@bitmap, ' + @index2 + ', ' + @len_after + ') ' exec dbo.sp_MSflush_command @cmd, 1 end select @cmd = N' select @version_guid = newid() ' insert into #proctext(procedure_text) values(@cmd) -- Partition check statement if @filter_clause IS NOT NULL begin declare @retcode int exec @retcode = sp_MSsubst_filter_names NULL, N'inserted', @filter_clause output if @retcode <> 0 or @@error <> 0 return 1 select @cmd = N' if exists (select * from inserted where not (' insert into #proctext(procedure_text) values(@cmd) -- break filter_clause into chunks of 255 select @start = 1 while @start < len(@filter_clause) begin if len(@filter_clause) < 255 select @sub_len = len(@filter_clause) else select @sub_len = 255 select @cmd = substring(@filter_clause, @start, @sub_len) exec dbo.sp_MSflush_command @cmd output, 1 select @start = @start + @sub_len end select @cmd = N')) begin exec sp_MSreplraiserror 21034 goto FAILURE end ' insert into #proctext(procedure_text) values(@cmd) end -- trigger nesting checks if @op_type in ('upd') begin select @cmd = N' ' + '-- trigger nesting check ' + '-- error = -1, nested call = 1, not a nested call = 0 exec @retcode = dbo.sp_check_sync_trigger @@procid, @trigger_op OUTPUT, N''' + master.dbo.fn_MSgensqescstr(@subtableowner) collate database_default + ''' if (@retcode = -1) goto FAILURE if (@retcode = 1) return ' insert into #proctext(procedure_text) values(@cmd) end END go raiserror('Creating procedure sp_MSscript_begintrig2', 0,1) go create procedure sp_MSscript_begintrig2 ( @publisher sysname ,@publisher_db sysname ,@publication sysname ,@objid int ,@op_type char(3) = 'ins' -- ins, upd, del ,@agent_id int ,@fisqueued bit = 0 -- 1 = Queued subscription ) as BEGIN declare @cmd nvarchar(4000) ,@queue_server sysname ,@subtableowner sysname select @subtableowner = user_name(objectproperty(@objid, N'OwnerId')) if @op_type = 'ins' begin insert into #proctext(procedure_text) values(N' if Objectproperty(@@procid,''TriggerInsertOrder'') != 1 begin declare @trigname sysname select @trigname = object_name(@@procid) raiserror (21128, 16, 1, @trigname) goto FAILURE end ') end else if @op_type = 'upd' begin insert into #proctext(procedure_text) values(N' if Objectproperty(@@procid,''TriggerUpdateOrder'') != 1 begin declare @trigname sysname select @trigname = object_name(@@procid) raiserror (21129, 16, 1, @trigname) goto FAILURE end ') end else if @op_type = 'del' begin insert into #proctext(procedure_text) values(N' if Objectproperty(@@procid,''TriggerDeleteOrder'') != 1 begin declare @trigname sysname select @trigname = object_name(@@procid) raiserror (21130, 16, 1, @trigname) goto FAILURE end ') end -- -- scripting for debug messages -- select @cmd = N' select @update_mode_id = update_mode from dbo.MSsubscription_agents where id = ' + convert(nvarchar(10), @agent_id) + N' ' insert into #proctext(procedure_text) values (@cmd) -- -- continue with scripting -- select @cmd = N' ' + N'-- ' + N'-- initialize and validate based on update mode ' + N'-- if @update_mode_id = 1 begin exec @retcode = dbo.sp_MSget_publisher_rpc @@procid, @connect_string output, N''' + master.dbo.fn_MSgensqescstr(@subtableowner) collate database_default + ''' if @retcode <>0 or @@error <> 0 goto FAILURE end' insert into #proctext(procedure_text) values (@cmd) -- -- continue with scripting -- if (@fisqueued = 1) begin -- -- Queued specific scripting -- select @cmd = N' else if @update_mode_id in (2,4) begin select @queue_server = queue_server, @queue_id = queue_id from dbo.MSsubscription_agents where id = ' + convert(nvarchar(10), @agent_id) + N' if (@queue_id is NULL) goto FAILURE end' insert into #proctext(procedure_text) values (@cmd) -- -- continue with scripting -- select @cmd = N' else if @update_mode_id in (3,5) begin select @queue_server = queue_server, @queue_id = queue_id from dbo.MSsubscription_agents where id = ' + convert(nvarchar(10), @agent_id) + N' and failover_mode = 1 ' insert into #proctext(procedure_text) values (@cmd) -- -- continue with scripting -- select @cmd = N' if (@queue_id is NULL) begin exec @retcode = dbo.sp_MSget_publisher_rpc @@procid, @connect_string output, N''' + master.dbo.fn_MSgensqescstr(@subtableowner) collate database_default + ''' if @retcode <>0 or @@error <> 0 goto FAILURE end end' insert into #proctext(procedure_text) values (@cmd) end -- -- continue with scripting -- select @cmd = N' else if @update_mode_id = 0 begin raiserror (''read only mode - no updates allowed'', 16, 1) goto FAILURE end else begin raiserror(''invalid update mode %d'', 16, 1, @update_mode_id) goto FAILURE end ' insert into #proctext(procedure_text) values (@cmd) if (@fisqueued = 1) begin select @cmd = N' ' + N'-- ' + N'-- set queue prefix for MSMQ cases ' + N'-- if (@update_mode_id in (2,3)) begin select @queue_id = N''DIRECT=OS:'' + @queue_server + N''\PRIVATE$\'' + @queue_id end' insert into #proctext(procedure_text) values (@cmd) -- -- Get failover mode scripting -- select @cmd = N' ' + N'-- ' + N'-- get failover mode ' + N'-- if @update_mode_id in (3,5) begin select @failover_mode_id = failover_mode from dbo.MSsubscription_agents where id = ' + convert(nvarchar(10), @agent_id) + ' and update_mode in (3,5) end' insert into #proctext(procedure_text) values (@cmd) end -- -- Start the distributed tran and get the transaction id as we may use -- it for queue sends -- select @cmd = N' ' + N'-- ' + N'-- begin tran or dist tran based on update mode ' + N'-- if (@update_mode_id in (4,5)) BEGIN TRAN else BEGIN DISTRIBUTED TRAN ' insert into #proctext(procedure_text) values (@cmd) if (@fisqueued = 1) begin select @cmd = N' ' + N'-- ' + N'-- save the transaction token for later use ' + N'-- exec sp_getbindtoken @out_token = @tran_id OUTPUT , @for_xp_flag = 1 ' insert into #proctext(procedure_text) values (@cmd) end -- -- all done with scripting -- return 0 END go raiserror('Creating procedure sp_MSscript_endtrig', 0,1) go create proc sp_MSscript_endtrig as BEGIN declare @cmd nvarchar(4000) select @cmd = N' if (@@trancount > 0) commit tran return FAILURE: if (@@trancount > 0) begin exec sp_MSreplraiserror 20512 rollback tran end ' insert into #proctext(procedure_text) values(@cmd) END go raiserror('Creating procedure sp_MSscript_trigger_variables', 0,1) go create procedure sp_MSscript_trigger_variables ( @objid int, @prefix char(1) = null, -- null or '@' @postfix varchar(4) = null, @indent int = 0, @spacer nvarchar(1) = N' ', @bOutput_params tinyint = 0, -- declare output params if necessary @identity_col sysname = null, @ts_col sysname = null, @include_type bit = 0, @set_nulls bit = 0, @op_type char(3) = 'ins', -- 'ins, 'upd', 'del' @is_new bit = 0, @primary_key_bitmap varbinary(4000) = NULL, @no_output bit = 0 ) as begin declare @cmd nvarchar(4000) ,@colname sysname ,@ccoltype sysname ,@src_cols int ,@this_col int ,@total_col int ,@indkey int ,@fcreatedcolmap bit ,@rc int ,@column nvarchar(4000) declare @colmap table (relativeorder int identity(1,1), colid int) -- script cursor select variables select @cmd = N'' ,@indkey = 1 ,@fcreatedcolmap = 0 select @src_cols = max(colid) ,@total_col = count(colid) from syscolumns where id = @objid exec dbo.sp_MSpad_command @cmd output, @indent -- -- check if column Id match relative column order -- for trigger scripting -- if (@total_col < @src_cols) begin -- -- this table may have altered columns, so when we need to -- set a mapping for using the bitmaps properly as the bitmap -- always refers relative column order -- insert into @colmap (colid) select colid from syscolumns where id = @objid order by colid if (@@error != 0) begin raiserror('Could not create column mapping', 16, -1) return (1) end select @fcreatedcolmap = 1 end while (@indkey <= @total_col) begin -- -- set the actual column id for this relative order in the bitmap if necessary -- if (@fcreatedcolmap = 1) begin select @this_col = colid from @colmap where relativeorder = @indkey end else begin select @this_col = @indkey end -- -- Get column name -- Don't include timestamp or computed columns -- exec @rc = dbo.sp_MSget_colinfo @objid, @this_col, null, 0, @colname output, @ccoltype output if @rc = 0 and EXISTS (select name from syscolumns where id=@objid and colid=@this_col and iscomputed<>1 and xtype <> 189) begin if @prefix is null begin if (@set_nulls = 1) begin -- Optimization: -- Get null or actual column name -- Note: the output is quoted. exec dbo.sp_MSget_synctran_column @ts_col = @ts_col, @op_type = @op_type, -- 'ins, 'upd', 'del' @is_new = @is_new, @primary_key_bitmap = @primary_key_bitmap, @colname = @colname, @this_col = @this_col, @column = @column output, @from_proc = 0, @coltype = @ccoltype, @type = NULL, @art_col = @indkey select @cmd = @cmd + @spacer + @column + isnull(@postfix, N'') end else begin -- set null is false select @cmd = @cmd + @spacer + N'[' + @colname + isnull(@postfix, N'') + N']' end end else begin -- prefix was specified select @cmd = @cmd + @spacer + isnull(@prefix, N'') + N'c' + RTRIM(convert(nvarchar(4), @this_col)) + isnull(@postfix, N'') end if (@include_type = 1) begin declare @typestring nvarchar(100) exec dbo.sp_MSget_type @objid, @this_col, @colname output, @typestring OUTPUT select @cmd = @cmd + N' ' + @typestring end -- new vars of type timestamp and identity are declared as output params if (@bOutput_params = 1 and (@ccoltype = N'timestamp' or ColumnProperty(@objid, @colname, 'IsIdentity') = 1)) or (@colname = @identity_col or @colname = @ts_col) begin -- YWU: Do this to avoid output in cursor declaration statement. -- The right thing seems to be set output only when bOutput_params is set -- but it seems not the way this sp is called. if @set_nulls = 0 and @no_output = 0 select @cmd = @cmd + N' output' end select @spacer = N',' end -- if rc=0 and exists ... exec dbo.sp_MSflush_command @cmd output, 0, @indent select @indkey = @indkey + 1 end -- while () loop exec dbo.sp_MSflush_command @cmd output, 1, @indent insert into #proctext(procedure_text) values(N' ') end go raiserror('Creating procedure sp_MSscript_trigger_assignment', 0,1) go create procedure sp_MSscript_trigger_assignment ( @objid int ,@postfix char(4) = null ,@indent int = 0 ,@ts_col sysname ,@op_type char(3) -- 'ins, 'upd', 'del' ,@is_new bit ,@primary_key_bitmap varbinary(4000) = null ) as BEGIN declare @cmd nvarchar(4000) ,@colname sysname ,@spacer nvarchar(1) ,@ccoltype sysname ,@src_cols int ,@this_col int ,@total_col int ,@indkey int ,@fcreatedcolmap bit ,@rc int ,@column nvarchar(4000) declare @colmap table (relativeorder int identity(1,1), colid int) -- initialize select @spacer = N' ' ,@indkey = 1 ,@fcreatedcolmap = 0 select @src_cols = max(colid) ,@total_col = count(colid) from syscolumns where id = @objid exec dbo.sp_MSpad_command @cmd output, @indent -- -- check if column Id match relative column order -- for trigger scripting -- if (@total_col < @src_cols) begin -- -- this table may have altered columns, so when we need to -- set a mapping for using the bitmaps properly as the bitmap -- always refers relative column order -- insert into @colmap (colid) select colid from syscolumns where id = @objid order by colid if (@@error != 0) begin raiserror('Could not create column mapping', 16, -1) return (1) end select @fcreatedcolmap = 1 end while (@indkey <= @total_col) begin -- -- set the actual column id for this relative order in the bitmap if necessary -- if (@fcreatedcolmap = 1) begin select @this_col = colid from @colmap where relativeorder = @indkey end else begin select @this_col = @indkey end -- -- Get column name -- exec @rc = dbo.sp_MSget_colinfo @objid, @this_col, null, 0, @colname output, @ccoltype output if @rc = 0 and EXISTS (select name from syscolumns where id=@objid and @this_col=colid and iscomputed<>1) begin -- Optimization: -- Get null or actual column name -- Note: the output is quoted. exec dbo.sp_MSget_synctran_column @ts_col = @ts_col, @op_type = @op_type, -- 'ins, 'upd', 'del' @is_new = @is_new, @primary_key_bitmap = @primary_key_bitmap, @colname = @colname, @this_col = @this_col, @column = @column output, @from_proc = 0, @coltype = NULL, @type = NULL, @art_col = @indkey select @cmd = @cmd + @spacer + N'@c' + convert(sysname, @this_col) + isnull(@postfix, N'') + N' = ' + @column select @spacer = N',' end exec dbo.sp_MSflush_command @cmd output, 1, @indent select @indkey = @indkey + 1 end exec dbo.sp_MSflush_command @cmd output, 1, @indent END go raiserror('Creating procedure sp_MSscript_trigger_fetch_statement', 0,1) go create procedure sp_MSscript_trigger_fetch_statement ( @objid int, @op_type char(3) = 'ins', @indent int = 0 ) as BEGIN declare @cmd nvarchar(4000) -- script fetch statements if @op_type in ('ins', 'upd') begin exec dbo.sp_MSpad_command @cmd output, @indent select @cmd = @cmd + N'fetch next from rpl_ins_cursor into ' exec dbo.sp_MSflush_command @cmd output, 1, @indent exec dbo.sp_MSscript_trigger_variables @objid, '@', null, @indent, ' ' end if @op_type in ('ins') begin exec dbo.sp_MSpad_command @cmd output, @indent select @cmd = @cmd + N'fetch next from rpl_ins2_cursor into ' exec dbo.sp_MSflush_command @cmd output, 1, @indent exec dbo.sp_MSscript_trigger_variables @objid, '@', '_old', @indent, ' ' end if @op_type in ('upd', 'del') begin exec dbo.sp_MSpad_command @cmd output, @indent select @cmd = @cmd + N'fetch next from rpl_del_cursor into ' exec dbo.sp_MSflush_command @cmd output, 1, @indent exec dbo.sp_MSscript_trigger_variables @objid, '@', '_old', @indent, ' ' end END go raiserror('Creating procedure sp_MSscript_trigger_exec_rpc ', 0,1) go create procedure sp_MSscript_trigger_exec_rpc ( @publisher sysname, @publisherdb sysname, @publication sysname, @procname sysname, @proc_owner sysname, @cftproc sysname, @objid int, @op_type char(3) = 'ins', @indent int = 0, @identity_col sysname = null, @ts_col sysname = null, @primary_key_bitmap varbinary(4000), @pubversion int ) as BEGIN declare @cmd nvarchar(4000) ,@min_identity int ,@max_identity int ,@fisqueued bit ,@varindent int ,@object_owner sysname -- -- validate @op_type -- if (@op_type) not in ('ins', 'upd', 'del') return 1 select @fisqueued = case when (@cftproc is NULL) then 0 else 1 end -- -- Set version guid param and column first. -- if @op_type in ('upd') begin exec dbo.sp_MSscript_trigger_version_updates @objid, 'msrepl_tran_version', @indent, @primary_key_bitmap end -- -- continue scripting -- select @cmd = N' if (@update_mode_id = 1) or (@update_mode_id in (3, 5) and @failover_mode_id = 0) begin ' + N'-- ' + N'-- immediate mode - check if publisher is local ' + N'-- if @connect_string is null begin ' insert into #proctext(procedure_text) values (@cmd) -- -- prepare the proc invocation -- 1st two variables are subscriber server name and database name for cycle detection -- select @cmd = N' select @rpc_proc = N''' + quotename(@publisher) collate database_default + N'.' + quotename(master.dbo.fn_MSgensqescstr(@publisherdb)) collate database_default + N'.' + quotename(master.dbo.fn_MSgensqescstr(@proc_owner)) collate database_default + N'.' + quotename(master.dbo.fn_MSgensqescstr(@procname)) collate database_default + N''' exec @retcode = @rpc_proc @subscriber, @subscriber_db, ' insert into #proctext(procedure_text) values (@cmd) -- -- script the trigger variables -- select @min_identity = @@identity if @op_type in ('ins', 'upd') exec dbo.sp_MSscript_trigger_variables @objid, '@', N'', @indent, N'', 0, @identity_col, @ts_col if @op_type = 'upd' begin exec dbo.sp_MSscript_trigger_variables @objid, '@', '_old', @indent, ',', 0, null, null insert into #proctext(procedure_text) values (N' ,@bitmap') end else if @op_type = 'del' exec dbo.sp_MSscript_trigger_variables @objid, '@', '_old', @indent, ' ', 0, null, null select @max_identity = @@identity -- -- continue scripting -- select @cmd = N' if (@@error != 0 or @retcode != 0) begin if (@retcode = -2) exec sp_MSreplraiserror 21064 else if @retcode = 5 exec sp_MSreplraiserror 20515 else exec sp_MSreplraiserror 21054 goto FAILURE end end else begin' insert into #proctext(procedure_text) values (@cmd) -- -- prepare the RPC invocation -- select @cmd = N' select @rpc_proc = N'' declare @retcode int exec @retcode = '' + N' select @cmd = @cmd + quotename('OpenDataSource(''SQLOLEDB'',N' ,'''') select @cmd = @cmd + '+ '''''''' + replace(@connect_string, '''''''', '''''''''''''''') + N'''''''' + ' select @cmd = @cmd + 'N'').'' + N''' select @cmd = @cmd + quotename(master.dbo.fn_MSgensqescstr(@publisherdb)) collate database_default + '.' select @cmd = @cmd + quotename(master.dbo.fn_MSgensqescstr(@proc_owner)) collate database_default + '.' select @cmd = @cmd + quotename(master.dbo.fn_MSgensqescstr(@procname)) collate database_default + ''' + quotename(@subscriber) collate database_default + '','' + quotename(@subscriber_db) collate database_default + '', '' + ''' insert into #proctext(procedure_text) values (@cmd) -- -- script the trigger variables -- select @varindent = @indent + 4 if @op_type in ('ins', 'upd') exec dbo.sp_MSscript_trigger_variables @objid, '@', N'', 0, N'', 0, @identity_col, @ts_col if @op_type = 'upd' begin exec dbo.sp_MSscript_trigger_variables @objid, '@', 'o', @varindent, ',', 0, null, null insert into #proctext(procedure_text) values (N' ,@bitmap') end else if @op_type = 'del' exec dbo.sp_MSscript_trigger_variables @objid, '@', 'o', 0, ' ', 0, null, null -- -- Must raise error right before exiting the dynamic exec so that it will be picked up. -- select @cmd = N' '' + '' if (@@error != 0 or @retcode != 0) begin if (@retcode = -2) exec sp_MSreplraiserror 21064 else if @retcode = 5 exec sp_MSreplraiserror 20515 else exec sp_MSreplraiserror 21054 end'' ' insert into #proctext(procedure_text) values (@cmd) -- -- Get parameter datatypes -- insert into #proctext(procedure_text) values (N' select @rpc_types = ''') if @op_type in ('ins', 'upd') exec dbo.sp_MSscript_trigger_variables @objid, '@', N'' , 0, N'', 0, @identity_col, @ts_col, 1 if @op_type = 'upd' exec dbo.sp_MSscript_trigger_variables @objid, '@', 'o', @varindent, ',', 0, null, null, 1 else if @op_type = 'del' exec dbo.sp_MSscript_trigger_variables @objid, '@', 'o', 0, ' ', 0, null, null, 1 exec dbo.sp_MSpad_command @cmd output, @indent select @cmd = @cmd + N'''' insert into #proctext(procedure_text) values (@cmd) if @op_type = 'upd' begin insert into #proctext(procedure_text) values (N' select @rpc_types = @rpc_types + '', @bitmap varbinary(4000)'' ') end -- -- make rpc call -- insert into #proctext(procedure_text) values (N' exec @retcode = dbo.sp_executesql @rpc_proc, @rpc_types, ') -- -- Get parameters again -- insert into #proctext(procedure_text) select procedure_text from #proctext where c1 > @min_identity and c1 <= @max_identity order by c1 asc -- -- continue scripting -- select @cmd = N' if @@error != 0 goto FAILURE end end ' insert into #proctext(procedure_text) values (@cmd) if (@fisqueued = 1) begin declare @artidstring sysname ,@qversion int ,@foldqueuestyle bit -- -- Check the publisher version -- if (@pubversion = 1) begin -- -- Publisher is PreSP3 -- Use the new style of parameter passing - Queue version 1 -- select @foldqueuestyle = 1 end else if (@pubversion > 1) begin -- -- Publisher is SP3 or later -- get the article id as string -- Use the new style of parameter passing - Queue version 2 -- select @artidstring = cast(artid as sysname) from (dbo.MSsubscription_articles as a join dbo.MSsubscription_agents as b on a.agent_id = b.id) where b.publisher = UPPER(@publisher) and b.publisher_db = @publisherdb and b.publication = @publication and a.dest_table = object_name(@objid) select @foldqueuestyle = 0 end else begin -- -- bad publisher version -- return 1 end -- -- Are we going old style - for backwards compatibility for SQL Queue -- For MSMQ we use a newer clsid for queue version and will -- use whatever is assigned to the queue during its creation -- A newer publisher will imply a newer distributor and we are -- okay. -- if (@foldqueuestyle = 1) begin -- -- Update the version on the sql queue to v1 if necessary -- update dbo.MSsubscription_agents set queue_id = 'mssqlqueue' where publisher = UPPER(@publisher) and publisher_db = @publisherdb and publication = @publication and update_mode in (4,5) and queue_id != 'mssqlqueue' end else begin -- -- Update the version on the sql queue to v2 if necessary -- update dbo.MSsubscription_agents set queue_id = 'mssqlqueuev2' where publisher = UPPER(@publisher) and publisher_db = @publisherdb and publication = @publication and update_mode in (4,5) and queue_id != 'mssqlqueuev2' end -- -- continue scripting -- select @cmd = N' else begin ' + N'-- ' + N'-- handle queued cases ' + N'-- if (@update_mode_id in (2,3)) begin' insert into #proctext(procedure_text) values (@cmd) -- -- MSMQ based write -- if (@foldqueuestyle = 1) begin -- -- old style scripting - non secure -- select @cmd = N' exec @retcode = master.dbo.sp_replsendtoqueue @queue_id, @tran_id, N' + quotename(@publication, '''') + N', N' + quotename(@cftproc, '''') + N', N' + quotename(@proc_owner, '''') + N', N' + quotename(@procname, '''') + N', @subscriber, @subscriber_db, ' end else begin -- -- new style scripting - secure -- select @cmd = N' exec @retcode = master.dbo.sp_replsendtoqueue @queue_id, @tran_id, N' + quotename(@publication, '''') + N', N' + quotename(@artidstring, '''') + N', N' + quotename(@op_type, '''') + N', N' + quotename(@procname, '''') + N', @subscriber, @subscriber_db, ' end insert into #proctext(procedure_text) values (@cmd) -- -- script the trigger variables -- select @varindent = @indent + 8 select @min_identity = @@identity if @op_type in ('ins', 'upd') exec dbo.sp_MSscript_trigger_variables @objid, '@', N'', @varindent, N'', 0, @identity_col, @ts_col, @no_output = 1 if @op_type = 'upd' begin exec dbo.sp_MSscript_trigger_variables @objid, '@', '_old', @varindent, ',', 0, null, null, @no_output = 1 insert into #proctext(procedure_text) values (N' ,@bitmap') end else if @op_type = 'del' exec dbo.sp_MSscript_trigger_variables @objid, '@', '_old', @varindent, ' ', 0, null, null, @no_output = 1 select @max_identity = @@identity -- -- SQL Queued case -- we loop here if the command length exceeds queue message length and -- break the command into partial cmds and send it in more than one -- queue message -- select @cmd = N' end else if (@update_mode_id in (4,5)) begin select @partial_cmd = 1, @start_offset = 0, @end_offset = 0 while (@partial_cmd != 0) begin' insert into #proctext(procedure_text) values (@cmd) if (@foldqueuestyle = 1) begin -- -- old style scripting - non secure -- select @cmd = N' exec @retcode = master.dbo.sp_replwritetovarbin @start_offset, @end_offset output, @vb_buffer output, @vb_bufferlen output, N' + quotename(@publisher, '''') + N', N' + quotename(@publisherdb, '''') + N', N' + quotename(@publication, '''') + N', @tran_id, N' + quotename(@cftproc, '''') + N', N' + quotename(@proc_owner, '''') + N', N' + quotename(@procname, '''') + N', @subscriber, @subscriber_db, ' end else begin -- -- new style scripting - secure -- select @cmd = N' exec @retcode = master.dbo.sp_replwritetovarbin @start_offset, @end_offset output, @vb_buffer output, @vb_bufferlen output, N' + quotename(@publisher, '''') + N', N' + quotename(@publisherdb, '''') + N', N' + quotename(@publication, '''') + N', @tran_id, N' + quotename(@artidstring, '''') + N', N' + quotename(@op_type, '''') + N', N' + quotename(@procname, '''') + N', @subscriber, @subscriber_db, ' end insert into #proctext(procedure_text) values (@cmd) -- -- script the trigger variables -- select @min_identity = @@identity if @op_type in ('ins', 'upd') exec dbo.sp_MSscript_trigger_variables @objid, '@', N'', @varindent, N'', 0, @identity_col, @ts_col, @no_output = 1 if @op_type = 'upd' begin exec dbo.sp_MSscript_trigger_variables @objid, '@', '_old', @varindent, ',', 0, null, null, @no_output = 1 insert into #proctext(procedure_text) values (N' ,@bitmap') end else if @op_type = 'del' exec dbo.sp_MSscript_trigger_variables @objid, '@', '_old', @varindent, ' ', 0, null, null, @no_output = 1 select @max_identity = @@identity -- -- continue scripting -- select @cmd = N' if @@error != 0 or @retcode != 0 begin exec sp_MSreplraiserror 21052 goto FAILURE end' insert into #proctext(procedure_text) values(@cmd) -- -- handle partial messages -- select @object_owner = user_name(ObjectProperty(@objid, 'ownerid')) select @cmd = N' select @partial_cmd = case when (@end_offset > 0) then 1 else 0 end exec @retcode = sp_MSsendtosqlqueue @@procid, N' + quotename(@publisher, '''') + N', N' + quotename(@publisherdb, '''') + N', N' + quotename(@publication, '''') + N', N' + quotename(@object_owner, '''') + N', @tran_id, @vb_buffer, @vb_bufferlen, 1, @partial_cmd ' insert into #proctext(procedure_text) values(@cmd) -- -- continue scripting -- select @cmd = N' if @@error != 0 or @retcode != 0 begin exec sp_MSreplraiserror 21052 goto FAILURE end select @start_offset = @end_offset end end' insert into #proctext(procedure_text) values(@cmd) -- -- continue scripting -- select @cmd = N' if @@error <>0 or @retcode <> 0 begin exec sp_MSreplraiserror 21052 goto FAILURE end end ' insert into #proctext(procedure_text) values(@cmd) end -- -- all done -- return 0 END go raiserror('Creating procedure sp_MSscript_trigger_update_checks', 0,1) go create procedure sp_MSscript_trigger_update_checks( @objid int, @identity_col sysname, @ts_col sysname, @op_type varchar(3) = 'ins', -- 'ins', 'upd' @indent int = 0 ) as BEGIN declare @cmd nvarchar(4000) declare @colname sysname declare @ccoltype sysname declare @src_cols int declare @this_col int declare @rc int declare @qualname nvarchar(512) declare @indid int declare @key sysname declare @indkey int /* if @op_type = 'pk' begin select @indkey = 1 exec sp_MSget_qualified_name @objid, @qualname OUTPUT exec @indid = dbo.sp_MStable_has_unique_index @objid if @indid > 0 begin exec dbo.sp_MSpad_command @cmd output, @indent while @indkey < 16 and index_col(@qualname, @indid, @indkey) is not null begin select @key = index_col(@qualname, @indid, @indkey) select @cmd = N'if update(' + @key + N') ' exec dbo.sp_MSflush_command @cmd output, 1, @indent insert into #proctext(procedure_text) values(N'begin exec sp_MSreplraiserror 20517 goto FAILURE end ') select @indkey = @indkey + 1 end end end else begin */ -- Image cols select @src_cols = max(colid) from syscolumns where id = @objid select @this_col = 1 exec dbo.sp_MSpad_command @cmd output, @indent while @this_col <= @src_cols begin exec @rc = dbo.sp_MSget_colinfo @objid, @this_col, null, 1, @colname output, @ccoltype output if @rc = 0 and EXISTS (select name from syscolumns where id=@objid and @this_col=colid and iscomputed<>1) begin if @ccoltype in ('text','ntext','image') begin if @op_type = 'ins' begin select @cmd = N'if update(' + quotename(@colname) + ') ' exec dbo.sp_MSflush_command @cmd output, 1, 0 insert into #proctext(procedure_text) values(N' exec sp_MSreplraiserror 20508 ') end else if @op_type = 'upd' begin select @cmd = N'if update(' + quotename(@colname) + ') ' exec dbo.sp_MSflush_command @cmd output, 1, 0 insert into #proctext(procedure_text) values(N'begin exec sp_MSreplraiserror 20509 goto FAILURE end ') end end end select @this_col = @this_col + 1 end -- end -- identity col if @op_type = 'upd' and @identity_col is not null begin select @cmd = N'if update(' + quotename(@identity_col) + N') ' exec dbo.sp_MSflush_command @cmd, 1 insert into #proctext(procedure_text) values(N'begin exec sp_MSreplraiserror 20510 goto FAILURE end ') end -- timestamp col if @op_type = 'upd' and @ts_col is not null begin select @cmd = N'if update(' + quotename(@ts_col) + N') ' exec dbo.sp_MSflush_command @cmd, 1 insert into #proctext(procedure_text) values(N'begin exec sp_MSreplraiserror 20511 goto FAILURE end ') end END go raiserror('Creating procedure sp_MSscript_trigger_updates', 0,1) go create procedure sp_MSscript_trigger_updates @identity_col sysname, @ts_col sysname, @op_type char(3) = 'ins', -- 'ins', 'del' @objid int, @indent int = 0, @primary_key_bitmap varbinary(4000) = null as declare @cmd nvarchar(4000) declare @col sysname declare @qualname nvarchar(512) if @op_type = 'upd' begin -- Script out pk var assigment that used in sp_MSscript_where_clause exec dbo.sp_MSscript_pkvar_assignment @objid, NULL, 1, @identity_col, @ts_col, @primary_key_bitmap insert into #proctext(procedure_text) values(N' ') end exec sp_MSget_qualified_name @objid, @qualname OUTPUT if @ts_col is not null and OBJECTPROPERTY(@objid, 'tablehastimestamp') <> 1 begin insert into #proctext(procedure_text) values(N' ') exec dbo.sp_MSpad_command @cmd output, @indent exec dbo.sp_MSget_col_position @objid, null, @ts_col, @col output select @cmd = @cmd + N'update ' + @qualname + N' set ' + @ts_col + N' = @' + @col exec dbo.sp_MSflush_command @cmd, 1 exec dbo.sp_MSscript_where_clause @objid, null, 'trg pk', null, @indent, @op_type, @primary_key_bitmap end -- Reset to publisher's identity value if it is not an identity at the subscriber if @op_type = 'ins' and @identity_col is not null and OBJECTPROPERTY(@objid, 'tablehasidentity') <> 1 begin insert into #proctext(procedure_text) values(N' ') exec dbo.sp_MSpad_command @cmd output, @indent exec dbo.sp_MSget_col_position @objid, null, @identity_col, @col output select @cmd = @cmd + N'update ' + @qualname + N' set ' + @identity_col + N' = @' + @col exec dbo.sp_MSflush_command @cmd, 1 exec dbo.sp_MSscript_where_clause @objid, null, 'trg pk', null, @indent, @op_type, @primary_key_bitmap end go raiserror('Creating procedure sp_MSscript_trigger_version_updates', 0,1) go create procedure sp_MSscript_trigger_version_updates @objid int, @version_col sysname, @indent int = 0, @primary_key_bitmap varbinary(4000) as declare @cmd nvarchar(4000) declare @col sysname declare @qualname nvarchar(512) -- Script out pk var assigment that used in sp_MSscript_where_clause exec dbo.sp_MSscript_pkvar_assignment @objid, NULL, 1, null, null, @primary_key_bitmap insert into #proctext(procedure_text) values(N' ') exec dbo.sp_MSget_col_position @objid, null, @version_col, @col output -- Assign the param corresponding to version col to new guid exec dbo.sp_MSpad_command @cmd output, @indent select @cmd = @cmd + N'set @' + @col + N' = @version_guid ' exec dbo.sp_MSflush_command @cmd, 1 insert into #proctext(procedure_text) values(N' ') exec sp_MSget_qualified_name @objid, @qualname OUTPUT exec dbo.sp_MSpad_command @cmd output, @indent select @cmd = N'update ' + @qualname + N' set ' + @version_col + N' = @' + @col exec dbo.sp_MSflush_command @cmd, 1 exec dbo.sp_MSscript_where_clause @objid, null, 'trg pk', null, @indent, 'upd', @primary_key_bitmap go raiserror('Creating procedure sp_MSscript_singlerow_trigger', 0,1) go create procedure sp_MSscript_singlerow_trigger ( @objid int, @publisher sysname, @publisher_db sysname, @publication sysname, @procname sysname, @proc_owner sysname, @cftproc sysname, @identity_col sysname, @ts_col sysname, @op_type char(3) = 'ins', -- 'ins, 'upd', 'del' @primary_key_bitmap varbinary(4000) = NULL, @pubversion int ) as BEGIN declare @colname sysname ,@spacer nvarchar(1) ,@ccoltype sysname ,@this_col int ,@rc int ,@cmd nvarchar(4000) -- -- script update checks -- if @op_type in ('ins', 'upd') exec dbo.sp_MSscript_trigger_update_checks @objid, @identity_col, @ts_col, @op_type, 0 -- -- continue scripting -- select @cmd = N' ' + N'-- ' + N'-- Are we doing single or multi row trigger update ' + N'-- if (@rc = 1) begin ' + N'-- ' + N'-- single row trigger update ' + N'-- ' insert into #proctext(procedure_text) values(@cmd) -- -- script the trigger assignments -- if @op_type in ('ins', 'upd') begin select @cmd = N' select ' insert into #proctext(procedure_text) values(@cmd) exec dbo.sp_MSscript_trigger_assignment @objid, null, 8, @ts_col, @op_type, 1, @primary_key_bitmap select @cmd = N' from inserted ' insert into #proctext(procedure_text) values(@cmd) end if @op_type in ('ins') begin select @cmd = N' select ' insert into #proctext(procedure_text) values(@cmd) exec dbo.sp_MSscript_trigger_assignment @objid, '_old', 8, @ts_col, @op_type, 0, @primary_key_bitmap select @cmd = N' from inserted ' insert into #proctext(procedure_text) values(@cmd) end else if @op_type in ('upd', 'del') begin select @cmd = N' select ' insert into #proctext(procedure_text) values(@cmd) exec dbo.sp_MSscript_trigger_assignment @objid, '_old', 8, @ts_col, @op_type, 0, @primary_key_bitmap select @cmd = N' from deleted ' insert into #proctext(procedure_text) values(@cmd) end -- -- script the execution logic -- exec dbo.sp_MSscript_trigger_exec_rpc @publisher, @publisher_db, @publication, @procname, @proc_owner, @cftproc, @objid, @op_type, 12, @identity_col, @ts_col, @primary_key_bitmap, @pubversion -- -- script any updates to be done -- if @op_type in ('ins', 'upd') exec dbo.sp_MSscript_trigger_updates @identity_col, @ts_col, @op_type, @objid, 8, @primary_key_bitmap -- -- script the end (for single row change) -- select @cmd = N' end -- end of single row trigger update ' insert into #proctext(procedure_text) values(@cmd) -- -- all done -- return 0 END go raiserror('Creating procedure sp_MSscript_multirow_trigger', 0,1) go create procedure sp_MSscript_multirow_trigger ( @objid int, @publisher sysname, @publisher_db sysname, @publication sysname, @procname sysname, @proc_owner sysname, @cftproc sysname, @identity_col sysname, @ts_col sysname, @op_type char(3) = 'ins', -- 'ins, 'upd', 'del' @primary_key_bitmap varbinary(4000) = NULL, @pubversion int ) as BEGIN declare @cmd nvarchar(4000) -- -- start scripting -- select @cmd = N' else begin ' + N'-- ' + N'-- start of multirow row trigger update ' + N'-- ' insert into #proctext(procedure_text) values(@cmd) -- -- setup cursor over inserted table for ins & upd triggers -- if @op_type in ('ins', 'upd') begin select @cmd = N' declare rpl_ins_cursor CURSOR LOCAL FAST_FORWARD FOR select ' insert into #proctext(procedure_text) values(@cmd) exec dbo.sp_MSscript_trigger_variables @objid, null, null, 8, ' ', 0,@identity_col, @ts_col,0, 1, @op_type, 1, @primary_key_bitmap select @cmd = N' from inserted for read only open rpl_ins_cursor ' insert into #proctext(procedure_text) values(@cmd) end if @op_type in ('ins') begin select @cmd = N' declare rpl_ins2_cursor CURSOR LOCAL FAST_FORWARD FOR select ' insert into #proctext(procedure_text) values(@cmd) exec dbo.sp_MSscript_trigger_variables @objid, null, null, 8, ' ' select @cmd = N' from inserted for read only open rpl_ins2_cursor ' insert into #proctext(procedure_text) values(@cmd) end -- -- setup cursor over deleted table for upd & del triggers -- if @op_type in ('upd', 'del') begin select @cmd = N' declare rpl_del_cursor CURSOR LOCAL FAST_FORWARD FOR select ' insert into #proctext(procedure_text) values(@cmd) exec dbo.sp_MSscript_trigger_variables @objid, null, null, 8, ' ', 0,@identity_col, @ts_col,0, 1, @op_type, 0, @primary_key_bitmap select @cmd = N' from deleted for read only open rpl_del_cursor ' insert into #proctext(procedure_text) values(@cmd) end -- -- script fetch statement -- exec dbo.sp_MSscript_trigger_fetch_statement @objid, @op_type, 8 -- -- start the fetch loop -- select @cmd = N' while (@@fetch_status != -1) begin ' insert into #proctext(procedure_text) values(@cmd) -- -- script the execution logic -- exec dbo.sp_MSscript_trigger_exec_rpc @publisher, @publisher_db, @publication, @procname, @proc_owner, @cftproc, @objid, @op_type, 16, @identity_col, @ts_col, @primary_key_bitmap, @pubversion -- -- script any updates to be done -- if @op_type in ('ins', 'upd') exec dbo.sp_MSscript_trigger_updates @identity_col, @ts_col, @op_type, @objid, 8, @primary_key_bitmap -- -- do the next fetch -- insert into #proctext(procedure_text) values(N' ') exec dbo.sp_MSscript_trigger_fetch_statement @objid, @op_type, 12 -- -- release the cursors -- select @cmd = N' end -- cursor while loop' insert into #proctext(procedure_text) values(@cmd) if @op_type in ('ins', 'upd') begin select @cmd = N' close rpl_ins_cursor deallocate rpl_ins_cursor ' insert into #proctext(procedure_text) values(@cmd) end if @op_type = 'ins' begin select @cmd = N' close rpl_ins2_cursor deallocate rpl_ins2_cursor ' insert into #proctext(procedure_text) values(@cmd) end if @op_type in ('upd', 'del') begin select @cmd = N' close rpl_del_cursor deallocate rpl_del_cursor ' insert into #proctext(procedure_text) values(@cmd) end -- -- script the end (for single row change) -- select @cmd = N' end -- end of multi row trigger update ' insert into #proctext(procedure_text) values(@cmd) -- -- all done -- return 0 END go -- -- Name: sp_MSscript_sync_ins_trig -- -- Description: This proc is used during the scripting of publisher synctran trigger -- used by updating subscribers. This SP generates the script for INSERT synctran -- trigger.It is executed on subscriber during the subscription initialization phase. -- -- Parameter: Refer to the comments in the create procedure statement -- -- Returns: 1 or 0 0 = success -- -- Security: Public procedure - does subscribe security check. -- raiserror('Creating procedure sp_MSscript_sync_ins_trig', 0,1) go create procedure sp_MSscript_sync_ins_trig ( @objid int, @publisher sysname, @publisher_db sysname, @publication sysname, @trigname sysname, @procname sysname, @proc_owner sysname, @cftproc sysname, @agent_id int, @identity_col sysname = NULL, @ts_col sysname = NULL, @filter_clause nvarchar(4000), @primary_key_bitmap varbinary(4000), @pubversion int = 1 ) as BEGIN declare @colname sysname ,@cmd nvarchar(4000) ,@ins_cmd nvarchar(4000) ,@columns binary(32) ,@outvars nvarchar(4000) ,@rc int ,@qualname nvarchar(512) ,@fisqueued bit set nocount on -- -- security check -- exec @rc = sp_MSreplcheck_subscribe if @@error <> 0 or @rc <> 0 begin return (1) end exec sp_MSget_qualified_name @objid, @qualname OUTPUT if (LOWER(@cftproc) = N'null') begin select @fisqueued = 0 ,@cftproc = NULL end else select @fisqueued = 1 if @ts_col in ('null','NULL') select @ts_col = null if @identity_col in ('null','NULL') select @identity_col = null -- Create temp table create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null) -- 1st preamble common to all synctran procs exec dbo.sp_MSscript_begintrig1 @trigname, @objid, @procname, @filter_clause, 'ins', @fisqueued -- 2nd preamble common to all synctran procs exec dbo.sp_MSscript_begintrig2 @publisher, @publisher_db, @publication, @objid, 'ins',@agent_id, @fisqueued -- script single row handling exec @rc = dbo.sp_MSscript_singlerow_trigger @objid,@publisher, @publisher_db, @publication, @procname, @proc_owner, @cftproc, @identity_col, @ts_col, 'ins', @primary_key_bitmap, @pubversion -- script multi-row handling exec @rc = dbo.sp_MSscript_multirow_trigger @objid, @publisher, @publisher_db, @publication, @procname, @proc_owner, @cftproc, @identity_col, @ts_col, 'ins', @primary_key_bitmap, @pubversion -- script end of trigger exec dbo.sp_MSscript_endtrig -- send fragments to client select procedure_text from #proctext order by c1 asc END go exec dbo.sp_MS_marksystemobject sp_MSscript_sync_ins_trig go -- -- Name: sp_MSscript_sync_upd_trig -- -- Description: This proc is used during the scripting of publisher synctran trigger -- used by updating subscribers. This SP generates the script for UPDATE synctran -- trigger.It is executed on subscriber during the subscription initialization phase. -- -- Parameter: Refer to the comments in the create procedure statement -- -- Returns: 1 or 0 0 = success -- -- Security: Public procedure - does subscribe security check. -- raiserror('Creating procedure sp_MSscript_sync_upd_trig', 0,1) go create procedure sp_MSscript_sync_upd_trig ( @objid int, @publisher sysname, @publisher_db sysname, @publication sysname, @trigname sysname, @procname sysname, @proc_owner sysname, @cftproc sysname, @agent_id int, @identity_col sysname = NULL, @ts_col sysname = NULL, @filter_clause nvarchar(4000), @primary_key_bitmap varbinary(4000), @pubversion int = 1) as BEGIN declare @colname sysname ,@cmd nvarchar(4000) ,@ins_cmd nvarchar(4000) ,@columns binary(32) ,@outvars nvarchar(4000) ,@rc int ,@qualname nvarchar(512) ,@fisqueued bit set nocount on -- -- security check -- exec @rc = sp_MSreplcheck_subscribe if @@error <> 0 or @rc <> 0 begin return (1) end exec sp_MSget_qualified_name @objid, @qualname OUTPUT if (LOWER(@cftproc) = N'null') begin select @fisqueued = 0 ,@cftproc = NULL end else select @fisqueued = 1 if @ts_col in ('null','NULL') select @ts_col = null if @identity_col in ('null','NULL') select @identity_col = null -- Create temp table create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null) -- 1st preamble common to all synctran procs exec dbo.sp_MSscript_begintrig1 @trigname, @objid, @procname, @filter_clause, 'upd', @fisqueued -- prevent updating of unique index when 'row compare' conflict detection, since it would trickle -- back as a del/insert, and fail /* if @ts_col is null begin insert into #proctext(procedure_text) values(N' ') -- exec dbo.sp_MSscript_trigger_update_checks @objid, null, null, 'pk', 0 end */ -- 2nd preamble common to all synctran procs exec dbo.sp_MSscript_begintrig2 @publisher, @publisher_db, @publication, @objid, 'upd',@agent_id, @fisqueued -- script single row handling exec @rc = dbo.sp_MSscript_singlerow_trigger @objid,@publisher, @publisher_db, @publication, @procname, @proc_owner, @cftproc, @identity_col, @ts_col, 'upd', @primary_key_bitmap, @pubversion -- script multi-row handling exec @rc = dbo.sp_MSscript_multirow_trigger @objid,@publisher, @publisher_db, @publication, @procname, @proc_owner, @cftproc, @identity_col, @ts_col, 'upd', @primary_key_bitmap, @pubversion -- script end of trigger exec dbo.sp_MSscript_endtrig -- send fragments to client select procedure_text from #proctext order by c1 asc END go exec dbo.sp_MS_marksystemobject sp_MSscript_sync_upd_trig go -- -- Name: sp_MSscript_sync_del_trig -- -- Description: This proc is used during the scripting of publisher synctran trigger used by updating subscribers. -- This SP generates the script for DELETE synctran trigger.It is executed on subscriber during the -- subscription initialization phase. -- -- Parameter: Refer to the comments in the create procedure statement -- -- Returns: 1 or 0 0 = success -- -- Security: Public procedure - does subscribe security check. -- raiserror('Creating procedure sp_MSscript_sync_del_trig', 0,1) go create procedure sp_MSscript_sync_del_trig ( @objid int, @publisher sysname, @publisher_db sysname, @publication sysname, @trigname sysname, @procname sysname, @proc_owner sysname, @cftproc sysname, @agent_id int, @identity_col sysname = NULL, @ts_col sysname = NULL, @filter_clause nvarchar(4000), @primary_key_bitmap varbinary(4000), @pubversion int = 1 ) as BEGIN declare @colname sysname ,@cmd nvarchar(4000) ,@ins_cmd nvarchar(4000) ,@columns binary(32) ,@outvars nvarchar(4000) ,@rc int ,@qualname nvarchar(512) ,@fisqueued bit set nocount on -- -- security check -- exec @rc = sp_MSreplcheck_subscribe if @@error <> 0 or @rc <> 0 begin return (1) end exec sp_MSget_qualified_name @objid, @qualname OUTPUT if (LOWER(@cftproc) = N'null') begin select @fisqueued = 0 ,@cftproc = NULL end else select @fisqueued = 1 if @ts_col in ('null','NULL') select @ts_col = null if @identity_col in ('null','NULL') select @identity_col = null -- Create temp table create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null) -- 1st preamble common to all synctran procs exec dbo.sp_MSscript_begintrig1 @trigname, @objid, @procname, @filter_clause, 'del', @fisqueued -- 2nd preamble common to all synctran procs exec dbo.sp_MSscript_begintrig2 @publisher, @publisher_db, @publication, @objid, 'del', @agent_id, @fisqueued -- script single row handling exec @rc = dbo.sp_MSscript_singlerow_trigger @objid,@publisher, @publisher_db, @publication, @procname, @proc_owner, @cftproc, @identity_col, @ts_col, 'del', @primary_key_bitmap, @pubversion -- script multi-row handling exec @rc = dbo.sp_MSscript_multirow_trigger @objid,@publisher, @publisher_db, @publication, @procname, @proc_owner, @cftproc, @identity_col, @ts_col, 'del', @primary_key_bitmap, @pubversion -- script end of trigger exec dbo.sp_MSscript_endtrig -- send fragments to client select procedure_text from #proctext order by c1 asc END go exec dbo.sp_MS_marksystemobject sp_MSscript_sync_del_trig go raiserror('Creating procedure sp_MSget_synctran_column', 0,1) go create procedure sp_MSget_synctran_column ( @ts_col sysname, @op_type char(3), -- 'ins, 'upd', 'del' @is_new bit, @primary_key_bitmap varbinary(4000) = null, @colname sysname, @this_col int, -- position in source object @column nvarchar(4000) output, @from_proc bit = 0, @coltype sysname = NULL, @type varchar(10) = NULL, @art_col int = NULL -- position in the partition. ) as begin declare @bytestr nvarchar(10) ,@bitstr nvarchar(10) ,@typed_null nvarchar(255) -- -- if @art_col is not NULL then it means one of the following: -- 1) If we are scripting for triggers - then it means the subscriber -- table (destination table) was altered and column id do not match -- relative column order(as specified in PK bitmap or columns_updated()). -- The @art_col will represent the relative column order in the bitmap -- and @this_col will represent the actual column id -- -- 2) If we are scripting for synctran procedures on publisher - then -- @art_col represents the relative index of the column that is being -- replicated and @this_col represents the actual column id of the column -- -- if @art_col is NULL - then we will set it to the value of @this_col -- if (@art_col is NULL) select @art_col = @this_col select @typed_null = case when (@coltype is null) then N'NULL' else N'convert(' + @coltype + N', NULL)' end -- Optimization: -- If the column value is not needed, we set the corresponding -- param to null to reduce the network traffic. Here is the rule: -- For new values in update trigger, -- Set the param to column value or null depending on whether or -- or the column is updated. -- For old values -- if ts col is replicated and the current column is not the ts col -- and the column is not in primary key, set the param to null -- For other cases -- set the param to column values. -- Called by proc if @type = 'pk_var' begin select @bytestr = convert( nvarchar, 1 + (@art_col-1) / 8 ) select @bitstr = convert( nvarchar, power(2, (@art_col-1) % 8 ) ) select @column = N'case substring(@bitmap,' + @bytestr + N',1) & ' + @bitstr + N' when ' + @bitstr + N' then ' + N'@c'+ convert( nvarchar, @this_col ) + N' else ' + N'@c'+ convert( nvarchar, @this_col ) + N'_old end' end else if (@from_proc = 1) begin select @bytestr = convert( nvarchar, 1 + (@art_col-1) / 8 ) select @bitstr = convert( nvarchar, power(2, (@art_col-1) % 8 ) ) select @column = N'case substring(@bitmap,' + @bytestr + N',1) & ' + @bitstr + N' when ' + @bitstr + N' then ' + N'@c'+ convert( nvarchar, @this_col ) + N' else [' + @colname + N'] end' end -- Called in trigger, else if (@is_new = 1) and (@op_type = 'upd') begin -- @bitmap is set using columns_updated() at the beginning -- of the trigger. select @bytestr = convert( nvarchar, 1 + (@art_col-1) / 8 ) select @bitstr = convert( nvarchar, power(2, (@art_col-1) % 8 ) ) select @column = N'case substring(@bitmap,' + @bytestr + N',1) & ' + @bitstr + N' when ' + @bitstr + N' then [' + @colname + N'] ' + N' else ' + @typed_null +' end' end else if ((@is_new = 0) and (@ts_col is not null and @colname not in (@ts_col, N'msrepl_tran_version')) and (@primary_key_bitmap is not null and (substring(@primary_key_bitmap, 1 + (@art_col-1) / 8 , 1) & power(2, (@art_col-1) % 8 )) = 0)) select @column = @typed_null else select @column = N'[' + @colname + N'] ' -- Add a new line select @column = @column + N' ' end go -- -- Name: sp_addqueued_artinfo -- -- Description: This procedure is invoked by distribution agent to populate MSsubscription_articles -- with all the necessary article meta data for queued publications. This article meta data is later -- used for conflict viewing (de-centralized). Invoked on subscriber. -- -- Parameter: Refer to the comments in the create procedure statement -- -- Returns: 1 or 0 0 = success -- -- Security: Public procedure - does subscribe security check. -- raiserror('Creating procedure sp_addqueued_artinfo', 0,1) go CREATE PROCEDURE sp_addqueued_artinfo ( @artid int ,@article sysname ,@publisher sysname ,@publisher_db sysname ,@publication sysname ,@dest_table sysname ,@owner sysname ,@cft_table sysname ,@columns binary(32)) AS BEGIN set nocount on declare @agent_id int ,@update_mode int ,@retcode int -- -- security check -- exec @retcode = sp_MSreplcheck_subscribe if @@error <> 0 or @retcode <> 0 begin return (1) end -- -- Create system table MSsubscription_articles if it does not exist -- IF NOT EXISTS (SELECT * FROM sysobjects WHERE type = 'U' AND name = 'MSsubscription_articles') BEGIN CREATE TABLE dbo.MSsubscription_articles ( agent_id int NOT NULL, -- related entry in MSsubscription_agents artid int NOT NULL, -- article id article sysname, -- article name dest_table sysname, -- destination table owner sysname, cft_table sysname, -- conflict table columns binary(32) ) IF (@@ERROR != 0) begin raiserror('Debug:sp_addqueued_artinfo - create MSsubscription_articles failed', 16, 1) return (1) end CREATE UNIQUE CLUSTERED INDEX ucMSsubscription_articles ON dbo.MSsubscription_articles(agent_id, artid) IF (@@ERROR != 0) begin raiserror('Debug:sp_addqueued_artinfo - create index for MSsubscription_articles failed', 16, 1) return (1) end EXEC dbo.sp_MS_marksystemobject 'MSsubscription_articles' END -- -- insert the row for the given article -- select @agent_id = id, @update_mode = update_mode from MSsubscription_agents where UPPER(publisher) = UPPER(@publisher) and publisher_db = @publisher_db and publication = @publication if (@agent_id IS NULL) begin raiserror('Debug:sp_addqueued_artinfo - agent_id is null for [%s].[%s].[%s]', 16, 1, @publisher, @publisher_db, @publication) return (1) end -- If the subscription is read only or immediate, no need to article info. if @update_mode in (0,1) return 0 -- -- If MSMQ Queued mode - check if the subscriber is compliant for MSMQ 2.0 -- if (@update_mode in (2,3)) begin if ((platform() & 0x1) != 0x1) begin -- -- Win 9X platform -- raiserror(21334, 16, 1, '2.0') return (1) end -- -- Now we use xp_MSver to detect NT OS version -- MSMQ subscription only allowed for platforms that support MSMQ 2.0 -- version 5.0.2195 or higher -- create table #tosversion ( propid int, propname sysname collate database_default, value int, charvalue nvarchar(255) collate database_default) insert into #tosversion (propid, propname, value, charvalue) exec master.dbo.xp_msver N'WindowsVersion' declare @vervalue int ,@lobyte tinyint ,@hibyte tinyint ,@loword smallint ,@hiword smallint -- -- low order byte of low order word = OSmajor, high order byte of low order word = OSminor -- high order word = OSbuild -- select @vervalue = value from #tosversion where propname = N'WindowsVersion' select @loword = (@vervalue & 0xffff) ,@hiword = (@vervalue / 0x10000) & 0xffff select @lobyte = @loword & 0xff ,@hibyte = (@loword / 100) & 0xff drop table #tosversion -- -- check for OS major version -- if (@lobyte < 5) begin raiserror(21334, 16, 2, '2.0') return (1) end -- -- check for OS build version -- if (@lobyte = 5 and @hiword < 2195) begin raiserror(21334, 16, 3, '2.0') return (1) end end -- -- Check for owner - use current user for NULL value -- if (@owner IS NULL or lower(@owner) = N'null' collate database_default) select @owner = user_name() if exists (select * from MSsubscription_articles where agent_id = @agent_id and artid = @artid) delete MSsubscription_articles where agent_id = @agent_id and artid = @artid insert into MSsubscription_articles(agent_id, artid, article, dest_table, owner, cft_table, columns) values (@agent_id, @artid, @article, @dest_table, @owner, @cft_table, @columns) IF (@@ERROR != 0) begin raiserror('Debug:sp_addqueued_artinfo - insert failed', 16, 1) return (1) end -- -- Do the queue initialization here -- this way we can initialize Snapshot/Logbased queued tran from one place -- exec @retcode = dbo.sp_MSreset_queue @publisher, @publisher_db, @publication, @artid IF (@retcode != 0 or @@ERROR != 0) begin raiserror('Debug:sp_addqueued_artinfo - sp_MSreset_queue failed', 16, 1) return (1) end -- -- all done -- return 0 END go exec dbo.sp_MS_marksystemobject sp_addqueued_artinfo go raiserror('Creating procedure sp_addsynctriggers', 0,1) go CREATE PROCEDURE sp_addsynctriggers ( @sub_table sysname, -- table name @sub_table_owner sysname, -- table owner @publisher sysname, -- publishing server name @publisher_db sysname, -- publishing database name. If NULL then same as current db @publication sysname, -- publication name. @ins_proc sysname, @upd_proc sysname, @del_proc sysname, @cftproc sysname, @proc_owner sysname, @identity_col sysname = 'NULL', @ts_col sysname = 'NULL', @filter_clause nvarchar(4000) = 'NULL', @primary_key_bitmap varbinary(4000), @identity_support bit = 0, @independent_agent bit = 0 ,@distributor sysname -- distribution server name ,@pubversion int = 1 -- 1 = when this call is generated by pre SP3 publishers, 2 = SP3 or later ) AS BEGIN set nocount on declare @db sysname ,@trigname sysname ,@ins_trig sysname ,@upd_trig sysname ,@del_trig sysname ,@qual_ins_trig nvarchar(540) ,@qual_upd_trig nvarchar(540) ,@qual_del_trig nvarchar(540) ,@dbname sysname ,@ccols int ,@cnt int ,@retcode int ,@cmd nvarchar(4000) ,@merge_pub_object_bit int ,@synctran_bit int ,@object_id int ,@bitmap_str varchar(8000) ,@constraint_name sysname ,@quoted_name nvarchar(540) ,@qualname nvarchar(540) ,@loctrancount int select @merge_pub_object_bit = 128 ,@synctran_bit = 256 -- Security Check EXEC @retcode = dbo.sp_MSreplcheck_subscribe IF @@ERROR <> 0 or @retcode <> 0 RETURN(1) -- -- validate @pubversion -- if (@pubversion is null) select @pubversion = 1 if (@pubversion not in (1,2)) return 1 -- Dist Agent executes this sproc with 'implicit transasctions on'. -- We take care of our own transactions boundaries to get out of tran set implicit_transactions off select @loctrancount = @@trancount while @@trancount > 0 commit tran -- check valid server and database setting -- 1. nested trigger have to be on if exists (select * from master..sysconfigures where config = 115 and value = 0) begin raiserror(21081, 16, 1) return (1) end -- 2. db option: recursive trigger have to be off if DATABASEPROPERTY(db_name(), N'IsRecursiveTriggersEnabled') <> 0 begin raiserror(21082, 16, 1) return (1) end -- 2. db compatibility level have to be 7.0 if exists (select * from master..sysdatabases where dbid = db_id() and cmptlevel < 70) begin raiserror(21083, 16, 1) return (1) end if lower(@sub_table_owner) = N'null' select @qualname = QUOTENAME(@sub_table) else select @qualname = QUOTENAME(@sub_table_owner) + N'.' + QUOTENAME(@sub_table) -- Verify that table exists select @object_id = object_id (@qualname) if @object_id is null begin raiserror(20507, 16, 1, @qualname, 'sp_addsynctriggers') return (1) end -- Add default to timestamp, identity and version guid column if OBJECTPROPERTY(@object_id, 'tablehastimestamp') <> 1 begin select @constraint_name = 'MSrepl_synctran_ts_default_' + convert(nvarchar(10), @object_id) select @quoted_name = quotename(@ts_col) if @ts_col is not null and @ts_col not in ('null','NULL') and not exists (select * from sysobjects where name = @constraint_name) begin exec ('alter table ' + @qualname + ' add constraint ' + @constraint_name + ' default 0 for ' + @quoted_name ) if @@ERROR<>0 return 1 end end if OBJECTPROPERTY(@object_id, 'tablehasidentity') <> 1 begin select @constraint_name = 'MSrepl_synctran_identity_default_' + convert(nvarchar(10), @object_id) select @quoted_name = quotename(@identity_col) if @identity_col is not null and @identity_col not in ('null','NULL') and not exists (select * from sysobjects where name = @constraint_name) begin exec ('alter table ' + @qualname + ' add constraint ' + @constraint_name + ' default 0 for ' + @quoted_name ) if @@ERROR<>0 return 1 end end -- The default constraint is transfered with snapshot already for native publication. -- Need to detect to see if default constraint already there. select @quoted_name = 'msrepl_tran_version' declare @colid int select @colid = colid from syscolumns where id = @object_id and name = @quoted_name if not exists (select * from sysconstraints where id = @object_id and colid = @colid and status & 5 = 5) -- default begin select @constraint_name = 'MSrepl_tran_version_default_' + convert(nvarchar(10), @object_id) exec ('alter table ' + @qualname + ' add constraint ' + @constraint_name + ' default newid() for ' + @quoted_name ) if @@ERROR<>0 return 1 end -- -- determine if we should pass @cftproc to scripting of synctran trigger -- Check if the subscription needs scripting for queued replication. -- For publishers that are pre 80SP3 - cftproc should not be null -- that takes care of it. For publisher that 80SP3 or later - we need -- to validate the article information -- -- Check the version of the publisher -- if ((@pubversion = 2) and not (@cftproc is null or lower(@cftproc) = 'null')) begin -- -- Publisher is 80SP3 or later -- @cftproc should exist and article information should exist -- for this subscription -- if not exists (select artid from (dbo.MSsubscription_articles as a join dbo.MSsubscription_agents as b on a.agent_id = b.id) where b.publisher = UPPER(@publisher) and b.publisher_db = @publisher_db and b.publication = @publication and a.dest_table = object_name(@object_id)) begin -- -- There is no article information -- disable queued specific scripting -- select @cftproc = 'null' end end -- If MSsubscription_properties table does not exists, create one. if (LOWER(@cftproc) = 'null') begin exec @retcode = dbo.sp_MScreate_sub_tables @tran_sub_table = 0, @property_table = 1, @sqlqueue_table = 0 end else begin exec @retcode = dbo.sp_MScreate_sub_tables @tran_sub_table = 0, @property_table = 1, @sqlqueue_table = 1 end IF @@ERROR <> 0 or @retcode <> 0 RETURN(1) -- If no entry in MSsubscription_properties for this publication, add one. IF NOT EXISTS (select * from MSsubscription_properties where UPPER(publisher) = UPPER(@publisher) and publisher_db = @publisher_db and publication = @publication) BEGIN -- Use status rpc for local publisher declare @security_mode int declare @login sysname if UPPER(@@servername) = UPPER(@publisher) begin select @security_mode = 2 end else begin select @security_mode = 0 select @login = 'sa' end exec @retcode = dbo.sp_link_publication @publisher = @publisher, @publisher_db = @publisher_db, @publication = @publication, @security_mode = @security_mode, @login = @login, @password = NULL, @distributor = @distributor IF @@ERROR <> 0 or @retcode <> 0 RETURN(1) END if exists (select * from sysobjects where replinfo & @merge_pub_object_bit <> 0 and id = @object_id) begin raiserror(21063, 16, 1, @qualname) return (1) end -- Get agent_id declare @agent_id int -- First try to get the agent id initialized by the distribution agent declare @login_time datetime select @login_time = login_time from master..sysprocesses where spid = @@spid select @agent_id = id from MSsubscription_agents where spid = @@spid and login_time = @login_time -- If row not found, the current call is not from a distribution agent. Uses -- are creating trigger manually using the script generated by -- sp_script_synctran_triggers. -- Get the row using the publication name. However, it is possible that there are -- more than one qualifed rows with different subscription_type, for example -- pull and push subscriptions to share agent publications or subscriptions that has -- not been cleaned up. if @agent_id is null begin declare @num_dup_rows int select @agent_id = avg(id), @num_dup_rows = count(*) from MSsubscription_agents where publisher = @publisher and publisher_db = @publisher_db and publication = case @independent_agent when 0 then N'ALL' else @publication end and -- We know the subscription must be updateble. This -- is to reduce the chance of dup rows. update_mode <> 0 if @num_dup_rows > 1 begin -- Raise subscription already exist error -- This should rarely happen. RAISERROR (14058, 16, -1) return(1) end if @agent_id is null begin raiserror(20588, 16, -1) return(1) end end /* ** Create system table MSreplication_objects if it does not exist */ IF NOT EXISTS (SELECT * FROM sysobjects WHERE type = 'U' AND name = 'MSreplication_objects') BEGIN CREATE TABLE dbo.MSreplication_objects ( publisher sysname NULL, publisher_db sysname NULL, publication sysname NULL, object_name sysname NOT NULL, object_type char(2) NOT NULL ) IF @@ERROR <> 0 begin rollback transaction return (1) end CREATE UNIQUE CLUSTERED INDEX ucMSreplication_objects ON dbo.MSreplication_objects(object_name) EXEC dbo.sp_MS_marksystemobject 'dbo.MSreplication_objects' END -- Drop all replication triggers on the source object -- We should drop all because we don't support updatable subscriptions to -- multiple publications on same dest table. declare object_cursor CURSOR LOCAL FAST_FORWARD for select o.object_name, so.id from MSreplication_objects o, sysobjects so where o.object_name = so.name and so.parent_obj = @object_id and o.object_type = 'T' declare @old_id int declare @old_name sysname OPEN object_cursor FETCH object_cursor INTO @old_name, @old_id WHILE (@@fetch_status <> -1) BEGIN -- Cleanup identity range table declare @parent_obj int select @parent_obj = 0 select @parent_obj = parent_obj from sysobjects where id = @old_id if exists (select * from sysobjects where name = 'MSsub_identity_range') delete MSsub_identity_range where objid = @parent_obj -- Drop the trigger exec @retcode = dbo.sp_MSdrop_object @object_id = @old_id if @retcode <> 0 or @@error <> 0 goto UNDO delete from MSreplication_objects where object_name=@old_name FETCH object_cursor INTO @old_name, @old_id END CLOSE object_cursor DEALLOCATE object_cursor -- Generate trigger names select @trigname = RTRIM(SUBSTRING(@sub_table,1,110)) select @ins_trig = N'trg_MSsync_ins_' + @trigname select @upd_trig = N'trg_MSsync_upd_' + @trigname select @del_trig = N'trg_MSsync_del_' + @trigname -- check uniqueness of names and revert to ugly guid-based name if friendly name already exists if exists (select name from sysobjects where name in (@ins_trig, @upd_trig, @del_trig)) begin declare @guid_name nvarchar(36) select @guid_name = convert (nvarchar(36), newid()) select @ins_trig = 'trg_MSsync_ins_' + @guid_name select @upd_trig = 'trg_MSsync_upd_' + @guid_name select @del_trig = 'trg_MSsync_del_' + @guid_name end -- Get qual names if lower(@sub_table_owner) = N'null' begin select @qual_ins_trig = @ins_trig select @qual_upd_trig = @upd_trig select @qual_del_trig = @del_trig end else begin select @qual_ins_trig = QUOTENAME(@sub_table_owner) + N'.' + @ins_trig select @qual_upd_trig = QUOTENAME(@sub_table_owner) + N'.' + @upd_trig select @qual_del_trig = QUOTENAME(@sub_table_owner) + N'.' + @del_trig end exec @retcode = master..xp_varbintohexstr @primary_key_bitmap, @bitmap_str output if @retcode <> 0 or @@error <> 0 return 1 /* exec ('if exists (select * from sysobjects where name = N''' + @ins_trig + N''' and xtype = N''TR'') drop trigger ' + @ins_trig) exec ('if exists (select * from sysobjects where name = N''' + @upd_trig + N''' and xtype = N''TR'') drop trigger ' + @upd_trig) exec ('if exists (select * from sysobjects where name = N''' + @del_trig + N''' and xtype = N''TR'') drop trigger ' + @del_trig) */ -- We are now going to create triggers, so start a transaction begin tran -- Call out to individual create trigger routines select @dbname = db_name() select @cmd = 'sp_MSscript_sync_ins_trig ' + convert( nvarchar, @object_id ) + ', N' + quotename(@publisher, '''') + ', N' + quotename(@publisher_db, '''') + ', N' + quotename(@publication, '''') + ', N' + quotename(@ins_trig, '''') + ', N' + quotename(@ins_proc, '''') + ', N' + quotename(@proc_owner, '''') + ', N' + quotename(@cftproc, '''') + ', ' + convert(nvarchar(10), @agent_id) + ', N' + quotename(@identity_col, '''') + ', N' + quotename(@ts_col, '''') if @filter_clause in ('NULL', 'null') select @cmd = @cmd + ', null' else select @cmd = @cmd + ', N''' + replace (@filter_clause,'''','''''') + '''' -- Set primary key bitmap and pubversion select @cmd = @cmd + ', ' + @bitmap_str + ', ' + cast(@pubversion as nvarchar(10)) exec @retcode = master..xp_execresultset @cmd, @dbname IF @@ERROR <> 0 or @retcode <> 0 goto UNDO select @cmd = 'sp_MSscript_sync_upd_trig ' + convert( nvarchar, @object_id ) + ', N' + quotename(@publisher, '''') + ', N' + quotename(@publisher_db, '''') + ', N' + quotename(@publication, '''') + ', N' + quotename(@upd_trig, '''') + ', N' + quotename(@upd_proc, '''') + ', N' + quotename(@proc_owner, '''') + ', N' + quotename(@cftproc, '''') + ', ' + convert(nvarchar(10), @agent_id) + ', N' + quotename(@identity_col, '''') + ', N' + quotename(@ts_col, '''') if @filter_clause in ('NULL', 'null') select @cmd = @cmd + ', null' else select @cmd = @cmd + ', N''' + replace (@filter_clause,'''','''''') + '''' -- Set primary key bitmap and pubversion select @cmd = @cmd + ', ' + @bitmap_str + ', ' + cast(@pubversion as nvarchar(10)) exec @retcode = master..xp_execresultset @cmd, @dbname IF @@ERROR <> 0 or @retcode <> 0 goto UNDO select @cmd = 'sp_MSscript_sync_del_trig ' + convert( nvarchar, @object_id ) + ', N' + quotename(@publisher, '''') + ', N' + quotename(@publisher_db, '''') + ', N' + quotename(@publication, '''') + ', N' + quotename(@del_trig, '''') + ', N' + quotename(@del_proc, '''') + ', N' + quotename(@proc_owner, '''') + ', N' + quotename(@cftproc, '''') + ', ' + convert(nvarchar(10), @agent_id) + ', N' + quotename(@identity_col, '''') + ', N' + quotename(@ts_col, '''') if @filter_clause in ('NULL', 'null') select @cmd = @cmd + ', null' else select @cmd = @cmd + ', N''' + replace (@filter_clause,'''','''''') + '''' -- Set primary key bitmap and pubversion select @cmd = @cmd + ', ' + @bitmap_str + ', ' + cast(@pubversion as nvarchar(10)) exec @retcode = master..xp_execresultset @cmd, @dbname IF @@ERROR <> 0 or @retcode <> 0 goto UNDO -- Drop old entries before insert. The triggers with those names -- are created as above. delete MSreplication_objects where object_name = @ins_trig IF @@ERROR <> 0 goto UNDO delete MSreplication_objects where object_name = @upd_trig IF @@ERROR <> 0 goto UNDO delete MSreplication_objects where object_name = @del_trig IF @@ERROR <> 0 goto UNDO -- Mark procedures as system procs so they don't show up in the UI exec dbo.sp_MS_marksystemobject @qual_ins_trig IF @@ERROR <> 0 goto UNDO insert into MSreplication_objects(publisher, publisher_db, publication, object_name, object_type) values(@publisher, @publisher_db, @publication, @ins_trig, 'T') IF @@ERROR <> 0 goto UNDO exec dbo.sp_MS_marksystemobject @qual_upd_trig IF @@ERROR <> 0 goto UNDO insert into MSreplication_objects(publisher, publisher_db, publication, object_name, object_type) values(@publisher, @publisher_db, @publication, @upd_trig, 'T') IF @@ERROR <> 0 goto UNDO exec dbo.sp_MS_marksystemobject @qual_del_trig IF @@ERROR <> 0 goto UNDO insert into MSreplication_objects(publisher, publisher_db, publication, object_name, object_type) values(@publisher, @publisher_db, @publication, @del_trig, 'T') IF @@ERROR <> 0 goto UNDO -- Mark the table for warnings in BCP update sysobjects set replinfo = replinfo | @synctran_bit where id = @object_id IF @@ERROR <> 0 goto UNDO -- Set up identity range table if @identity_support <> 0 begin if not exists (select * from sysobjects where name = 'MSsub_identity_range') begin create table dbo.MSsub_identity_range ( objid int not null, range bigint not null, last_seed bigint not null, threshold int not null) IF @@ERROR <> 0 goto UNDO CREATE UNIQUE CLUSTERED INDEX ucMSsub_identity_range ON dbo.MSsub_identity_range (objid) EXEC dbo.sp_MS_marksystemobject 'MSsub_identity_range' IF @@ERROR <> 0 goto UNDO end if not exists (select * from MSsub_identity_range where objid = @object_id) begin -- add zero at the beginning. insert into MSsub_identity_range (objid, range, last_seed, threshold) values (@object_id, 0, 0, 0) IF @@ERROR <> 0 goto UNDO end end -- commit tran commit tran -- Set trigger firing order for insert exec dbo.sp_settriggerorder @qual_ins_trig,'first','insert' exec dbo.sp_settriggerorder @qual_upd_trig,'first','update' exec dbo.sp_settriggerorder @qual_del_trig,'first','delete' -- Ignore errors. exec dbo.sp_MSsub_cleanup_orphans -- restore the trancount if necessary if (@loctrancount > 0) begin while (@@trancount < @loctrancount) begin tran end return (0) UNDO: if @@trancount <> 0 rollback tran return(1) END go -- -- Name: sp_setreplfailovermode -- -- Description: This SP is invoked on the subscriber to toggle the failover -- mode for immediate updating with failover to queued subscriptions. -- -- Parameter: Refer to the comments in the create procedure statement -- -- Returns: 1 or 0 0 = success -- -- Security: Public procedure - does subscribe security check. -- raiserror('Creating procedure sp_setreplfailovermode', 0,1) go create procedure sp_setreplfailovermode ( @publisher sysname, @publisher_db sysname, @publication sysname, @failover_mode nvarchar (10), @override tinyint = 0) as begin set nocount on declare @failover_mode_id tinyint, @current_failover_mode_id bit, @retcode int, @queue_id sysname, @fqueue_empty int, @update_mode int, @queue_server sysname -- -- security check -- exec @retcode = sp_MSreplcheck_subscribe if @@error <> 0 or @retcode <> 0 begin return (1) end -- -- validate @failover_mode -- if @failover_mode not in (N'immediate', N'sync', N'queued') begin raiserror (21184, 16, 1, '@failover_mode', 'immediate', 'sync', 'queued') return 1 end else begin if @failover_mode = 'immediate' or @failover_mode = 'sync' select @failover_mode_id = 0 else if @failover_mode = 'queued' select @failover_mode_id = 1 end -- -- Only valid to get/set failover_mode, -- if update_mode is failover (3,5) -- select @queue_id = queue_id, @queue_server = queue_server, @current_failover_mode_id = failover_mode, @update_mode = update_mode from MSsubscription_agents where UPPER(publisher) = UPPER(@publisher) and publisher_db = @publisher_db and publication = @publication and update_mode in (3,5) -- no such row exists if (@current_failover_mode_id is NULL) begin raiserror (21185, 16, 1) return 1 end -- should have a queue entry if (@queue_id is NULL) begin raiserror(21186, 16, 1, @publisher) return 1 end -- -- do the transition -- if ((@current_failover_mode_id = 0 and @failover_mode_id = 0) or (@current_failover_mode_id = 1 and @failover_mode_id = 1)) begin -- -- Going from immediate to immediate, queued to queued is no-op -- raiserror (21187, 16, 1) end else if (@current_failover_mode_id = 0 and @failover_mode_id = 1) begin -- -- Going from immediate to queued : update MSsubscription_agents -- update MSsubscription_agents set failover_mode = @failover_mode_id where UPPER(publisher) = UPPER(@publisher) and publisher_db = @publisher_db and publication = @publication and update_mode in (3,5) raiserror (21188, 10, 1, 'immediate', 'queued') end else if (@current_failover_mode_id = 1 and @failover_mode_id = 0) begin -- -- Going from queued to immediate : if override is not set -- then check if the queue is empty and then allow if empty. -- If override is set, just update MSsubscription_agents -- if (@override = 0) begin if (@update_mode = 3) begin -- -- MSMQ processing -- prefix the queue_id with queue server in direct format -- and then perform peek in the queue -- select @queue_id = N'DIRECT=OS:' + @queue_server + N'\PRIVATE$\' + @queue_id exec @retcode = master.dbo.xp_peekqueue @queue_id, @fqueue_empty output, 0 if (@@error != 0 or @retcode != 0) begin raiserror('sp_setreplfailovermode(debug): xp_peekqueue execution failed', 16, 1) return 1 end if (@fqueue_empty != 1) begin raiserror(21189, 16, 1, @queue_id) return 1 end end else begin -- -- SQL Queue processing -- if exists (select * from MSreplication_queue where publisher = UPPER(@publisher) and publisher_db = @publisher_db and publication = @publication ) begin raiserror(21189, 16, 2, @queue_id) return 1 end end end else begin raiserror(21190, 10, 1, 'queued', 'immediate') end -- -- update MSsubscription_agents -- update MSsubscription_agents set failover_mode = @failover_mode_id where publisher = @publisher and publisher_db = @publisher_db and publication = @publication and update_mode in (3,5) raiserror (21188, 10, 1, 'queued', 'immediate') end -- All done return 0 end go exec dbo.sp_MS_marksystemobject sp_setreplfailovermode go -- -- Name: sp_helpreplfailovermode -- -- Description: This SP is used by Queued replication user and -- Replication UI to find out the failover state of a given queued subscription. -- Invoked on the subscriber -- -- Parameter: Refer to the comments in the create procedure statement -- -- Returns: 1 or 0 0 = success -- -- Security: Public procedure - does subscribe security check. -- raiserror('Creating procedure sp_helpreplfailovermode', 0,1) go create procedure sp_helpreplfailovermode ( @publisher sysname, @publisher_db sysname, @publication sysname, @failover_mode_id tinyint = 0 output, @failover_mode nvarchar(10) = NULL output) as BEGIN declare @subfound bit ,@retcode int -- -- security check -- exec @retcode = sp_MSreplcheck_subscribe if @@error <> 0 or @retcode <> 0 begin return (1) end -- -- Check if the table MSsubscription_agents exists -- if exists (select * from dbo.sysobjects where name = 'MSsubscription_agents') begin -- -- Only valid to get failover_mode, if failover_mode is failover (3,5) -- if exists (select * from dbo.MSsubscription_agents where publisher = @publisher and publisher_db = @publisher_db and publication = @publication and update_mode in (3,5) ) select @subfound = 1 else select @subfound = 0 end else select @subfound = 0 -- -- Did we find an entry for initialized failover subscription -- if (@subfound = 0) begin -- -- Three possibilities : uninitialized subscription, non existent subscription -- or a non-mixed mode. Check If we have a PULL uninitialized subscription -- if exists (select * from dbo.sysobjects where name = 'MSreplication_subscriptions') begin if exists (select * from dbo.MSreplication_subscriptions where publisher = @publisher and publisher_db = @publisher_db and publication = @publication and update_mode in (3,5) ) begin -- -- unitialized PULL subscription : return the default values -- select @failover_mode_id = 0 select @subfound = 1 end end if (@subfound = 0) begin raiserror ('sp_helpreplfailovermode: Subscription for [%s].[%s].[%s] either has not been initialized or does not exist or does not support mixed mode', 16, 1, @publisher, @publisher_db, @publication) return 1 end end else begin -- -- we found our subscription -- select @failover_mode_id = failover_mode from dbo.MSsubscription_agents where publisher = @publisher and publisher_db = @publisher_db and publication = @publication and update_mode in (3,5) -- -- initialize to 'immediate' if necessary -- if @failover_mode_id not in (0, 1) begin raiserror ('sp_helpreplfailovermode: invalid failover_mode value %d for [%s].[%s].[%s], setting to 0 [immediate]', 11, 1, @failover_mode_id, @publisher, @publisher_db, @publication) update dbo.MSsubscription_agents set failover_mode = 0 where publisher = @publisher and publisher_db = @publisher_db and publication = @publication and update_mode in (3,5) select @failover_mode_id = 0 end end -- -- prepare the output -- select @failover_mode = case when @failover_mode_id = 0 then N'immediate' when @failover_mode_id = 1 then N'queued' end select N'failover_mode value' = @failover_mode_id, N'failover_mode' = @failover_mode -- -- all done -- return 0 END go exec dbo.sp_MS_marksystemobject sp_helpreplfailovermode go raiserror('Creating procedure sp_helpreplicationdboption', 0,1) go CREATE PROCEDURE sp_helpreplicationdboption ( @dbname sysname = '%', @type sysname = 'replication allowed' ) AS BEGIN SET NOCOUNT ON /* ** Declarations. */ DECLARE @retcode int ,@typebit int ,@distbit int -- bit to distinguish distribution databases ,@dbowner bit ,@dbreadonly bit ,@replication_db sysname SELECT @distbit = 16 ,@dbowner = 0 ,@dbreadonly = 0 -- don't do security check. if (lower(@type collate SQL_Latin1_General_CP1_CS_AS) like 'publish%') select @typebit = 1 else if (lower(@type collate SQL_Latin1_General_CP1_CS_AS) like 'subscribe%') select @typebit = 2 else if (lower(@type collate SQL_Latin1_General_CP1_CS_AS) like 'merge publish%') select @typebit = 4 else if (lower(@type collate SQL_Latin1_General_CP1_CS_AS) like 'merge subscribe%') select @typebit = 8 else if (lower(@type collate SQL_Latin1_General_CP1_CS_AS) like 'replication allowed%') select @typebit = 0 else begin raiserror(14091,-1,-1) return 1 end /* ** Parameter Check: @dbname. ** Check to make sure that the database name conforms to the rules ** for identifiers. */ IF @dbname <> '%' BEGIN EXECUTE @retcode = dbo.sp_validname @dbname IF @@ERROR <> 0 OR @retcode <> 0 RETURN (1) END /* ** Show databases with this option enabled. */ CREATE TABLE #replicationdbs (name sysname collate database_default not null, id int identity NOT NULL, transpublish bit not null, mergepublish bit not null, dbowner bit not null, dbreadonly bit not null) if @typebit <> 0 begin INSERT INTO #replicationdbs (name, transpublish, mergepublish, dbowner, dbreadonly) SELECT name, case when (category & 1) <> 0 then 1 else 0 end, case when (category & 4) <> 0 then 1 else 0 end, @dbowner, DATABASEPROPERTY(name, N'IsReadOnly') FROM master.dbo.sysdatabases WHERE ((@dbname = N'%') OR (name = @dbname collate database_default)) AND (category & @typebit) <> 0 AND (HAS_DBACCESS ( name ) = 1) DECLARE hCdboinfo CURSOR LOCAL FAST_FORWARD FOR SELECT name FROM #replicationdbs FOR READ ONLY OPEN hCdboinfo FETCH hCdboinfo INTO @replication_db WHILE (@@fetch_status <> -1) BEGIN EXEC @retcode = sp_MSrepl_isdbowner @replication_db IF (@retcode IS NOT NULL) AND (@retcode <> 0) BEGIN UPDATE #replicationdbs set dbowner = 1 where name = @replication_db END FETCH hCdboinfo INTO @replication_db END CLOSE hCdboinfo DEALLOCATE hCdboinfo end else begin DECLARE @db_category int /* Filter out distribution databases */ DECLARE hC CURSOR LOCAL FAST_FORWARD FOR SELECT name, category, DATABASEPROPERTY(name, N'IsReadOnly') FROM master.dbo.sysdatabases WHERE ((@dbname = N'%') OR (name = @dbname collate database_default)) AND (category & @distbit) = 0 AND (HAS_DBACCESS ( name ) = 1) FOR READ ONLY OPEN hC FETCH hC INTO @replication_db, @db_category, @dbreadonly WHILE (@@fetch_status <> -1) BEGIN if @replication_db NOT IN ('master','model','tempdb','msdb','MSSQLWeb') BEGIN EXEC @retcode = sp_MSrepl_isdbowner @replication_db IF (@retcode IS NOT NULL) AND (@retcode <> 0) BEGIN SELECT @dbowner = 1 END ELSE BEGIN SELECT @dbowner = 0 END INSERT INTO #replicationdbs (name, transpublish, mergepublish, dbowner, dbreadonly) VALUES (@replication_db, case when (@db_category & 1) <> 0 then 1 else 0 end, case when (@db_category & 4) <> 0 then 1 else 0 end, @dbowner, @dbreadonly) END FETCH hC INTO @replication_db, @db_category, @dbreadonly END CLOSE hC DEALLOCATE hC end SELECT * FROM #replicationdbs -- DROP TABLE #replicationdbs END go raiserror('Creating procedure sp_MScheck_agent_instance', 0,1) GO CREATE PROCEDURE sp_MScheck_agent_instance @application_name sysname, @agent_type int = NULL as declare @count_pro int set nocount on select @count_pro = count(*) from master..sysprocesses where program_name = @application_name collate database_default -- type 3 is for 7.0 distribution agent backward compatibility. if @agent_type = 3 begin -- The distribution agent will before connecting to the publisher with unique -- application name if @count_pro > 0 raiserror (21036, 16, -1, 'distribution') end -- 10 is 7.5 version of the distribution agent. else if @agent_type = 10 begin -- The distribution agent will connecting to the publisher with unique -- application name and then check. if @count_pro > 1 raiserror (21036, 16, -1, 'distribution') end else if @agent_type = 4 begin -- The merge agent will connect to the publisher with unique application name -- then call this procedure if @count_pro > 1 raiserror (21036, 16, -1, 'merge') end else if @agent_type = 1 begin -- The snapshot agent will connect to the distributiondb with unique application name -- then call this procedure if @count_pro > 2 raiserror (21036, 16, -1, 'snapshot') end else if @agent_type = 2 begin -- The logreader agent will connect to the distributiondb with unique application name -- then call this procedure if @count_pro > 1 raiserror (21036, 16, -1, 'logreader') end else if @agent_type = 9 begin -- The queuereader agent will connect to the distributiondb with unique application name -- then call this procedure if @count_pro > 1 raiserror (21036, 16, -1, 'queuereader') end go CREATE PROCEDURE sp_MSBumpupCompLevel( @pubid uniqueidentifier, @new_level int ) as declare @retcode int /* ** Security Check */ EXEC @retcode = dbo.sp_MSreplcheck_publish IF @@ERROR <> 0 or @retcode <> 0 return (1) /* always bump UP, not Down in any case */ update sysmergepublications set backward_comp_level = @new_level where pubid=@pubid and backward_comp_level < @new_level if @@ERROR<>0 return (1) return (0) GO exec dbo.sp_MS_marksystemobject sp_MSBumpupCompLevel go CREATE PROCEDURE sp_MSCleanupForPullReinit ( @publication sysname, @publisher_db sysname, @publisher sysname = @@servername ) AS declare @pubid uniqueidentifier declare @artid uniqueidentifier declare @retcode smallint /* ** Security Check */ EXEC @retcode = dbo.sp_MSreplcheck_publish IF @@ERROR <> 0 or @retcode <> 0 return (1) /* This only gets called after database is enable to subscribe, so sysmergepublications should exist */ select @pubid = pubid FROM sysmergepublications WHERE name = @publication and UPPER(publisher)=UPPER(@publisher) and publisher_db = @publisher_db /* Normal case - nothing to cleanup, just return */ if @pubid is null return (1) begin transaction save tran cleanupforreinit /* ** Make sure you NULL out gen_cur for other articles that share this table ** since we are deleting the genhistroy row for that generation */ update sysmergearticles set gen_cur=NULL where gen_cur in (select generation from MSmerge_genhistory where pubid = @pubid) if @@ERROR<>0 goto Error delete from MSmerge_genhistory where pubid = @pubid if @@ERROR<>0 goto Error delete from sysmergesubsetfilters where pubid=@pubid if @@ERROR<>0 goto Error delete from sysmergeschemachange where pubid = @pubid if @@ERROR<>0 goto Error delete from MSmerge_contents where tablenick in (select nickname from sysmergearticles where pubid=@pubid) if @@ERROR<>0 goto Error delete from MSmerge_tombstone where tablenick in (select nickname from sysmergearticles where pubid=@pubid) if @@ERROR<>0 goto Error update MSmerge_replinfo set recgen = NULL, recguid = NULL, sentgen = NULL, sentguid = NULL where repid in ( select subid from sysmergesubscriptions where pubid = @pubid) if @@ERROR<>0 goto Error commit tran return (0) Error: rollback tran cleanupforreinit commit tran return (1) GO exec dbo.sp_MS_marksystemobject sp_MSCleanupForPullReinit go grant execute on dbo.sp_MSCleanupForPullReinit to public go raiserror('Creating procedure sp_MSpublicationcleanup', 0,1) GO CREATE PROCEDURE sp_MSpublicationcleanup ( @publication sysname, @publisher_db sysname, @publisher sysname = @@servername ) AS declare @pubid uniqueidentifier declare @artid uniqueidentifier declare @retcode smallint declare @objectname sysname declare @objectowner sysname /* ** Security Check */ EXEC @retcode = dbo.sp_MSreplcheck_publish IF @@ERROR <> 0 or @retcode <> 0 return (1) /* This only gets called after database is enable to subscribe, so sysmergepublications should exist */ select @pubid = pubid FROM sysmergepublications WHERE name = @publication and UPPER(publisher)=UPPER(@publisher) and publisher_db = @publisher_db /* Normal case - nothing to cleanup, just return */ if @pubid is null return (1) /* ** If we are deleting the last publication in the database, ie there are articles in ** sysmergearticles with a different pubid then the one being dropped ** then remove all the rows in MSmerge_genhistory, MSmerge_contents and MSmerge_tombstone ** use a truncate table in order to make the operation non logged and hence efficient */ if not exists (select * from sysmergearticles where pubid <> @pubid) begin truncate table MSmerge_genhistory truncate table MSmerge_contents truncate table MSmerge_tombstone end begin transaction save tran MSpublicationcleanup /* Clean up the articles for this publication, and delete the row */ select @artid = artid FROM sysmergearticles WHERE pubid = @pubid while @artid is not null begin if not exists (select * from sysmergearticles WHERE artid = @artid and pubid <> @pubid) begin exec @retcode=sp_MSarticlecleanup @pubid, @artid if @retcode<>0 or @@ERROR<>0 goto Error end delete from sysmergearticles where artid = @artid and pubid = @pubid if @@ERROR<>0 goto Error set @artid = NULL select @artid = artid FROM sysmergearticles WHERE pubid = @pubid end /* Unmark all schema articles in this publication */ if exists (select * from sysobjects where name = 'sysmergeschemaarticles') begin declare hschemaarticle_cur cursor local fast_forward for select destination_object, destination_owner from sysmergeschemaarticles where pubid = @pubid for read only open hschemaarticle_cur fetch hschemaarticle_cur into @objectname, @objectowner while (@@fetch_status<>-1) begin exec sp_MSunmarkschemaobject @objectname, @objectowner if @retcode<>0 or @@ERROR<>0 goto Error fetch hschemaarticle_cur into @objectname, @objectowner end close hschemaarticle_cur deallocate hschemaarticle_cur /* Delete all schema article rows for this publication*/ delete from sysmergeschemaarticles where pubid = @pubid if @@ERROR<>0 goto Error end /* Now clean up any traces in other system tables */ /* ** Make sure you NULL out gen_cur for other articles that share this table ** since we are deleting the genhistroy row for that generation */ update sysmergearticles set gen_cur=NULL where gen_cur in (select generation from MSmerge_genhistory where pubid = @pubid) if @@ERROR<>0 goto Error delete from MSmerge_genhistory where pubid = @pubid if @@ERROR<>0 goto Error delete from MSmerge_replinfo where repid in (select subid from sysmergesubscriptions where pubid = @pubid and status <> 2) if @@ERROR<>0 goto Error delete from sysmergesubsetfilters where pubid = @pubid if @@ERROR<>0 goto Error delete from sysmergesubscriptions where pubid = @pubid and status <> 2 if @@ERROR<>0 goto Error delete from sysmergepublications where pubid = @pubid if @@ERROR<>0 goto Error delete from sysmergeschemachange where pubid = @pubid if @@ERROR<>0 goto Error commit tran return (0) Error: rollback tran MSpublicationcleanup commit tran return (1) GO exec dbo.sp_MS_marksystemobject sp_MSpublicationcleanup go grant execute on dbo.sp_MSpublicationcleanup to public go raiserror('Creating procedure sp_removedbreplication', 0,1) GO create procedure sp_cleanupdbreplication AS set nocount on declare @pubid uniqueidentifier declare @artid uniqueidentifier declare @retcode int exec @retcode = sp_MSreplcheck_publish if (@retcode <> 0 or @@error <> 0) return 1 if not exists (select name from sysobjects where name='sysmergesubscriptions') return (0) declare #RemoveReplication CURSOR LOCAL FAST_FORWARD for select pubid from sysmergepublications open #RemoveReplication fetch #RemoveReplication into @pubid while (@@fetch_status<>-1) begin /* Clean up the articles for this publication, and delete the row */ select @artid = artid FROM sysmergearticles WHERE pubid = @pubid while @artid is not null begin if not exists (select * from sysmergearticles WHERE artid = @artid and pubid <> @pubid) begin exec @retcode=sp_MSarticlecleanup @pubid, @artid if @retcode<>0 or @@ERROR<>0 begin close #RemoveReplication deallocate #RemoveReplication return (1) end end delete from sysmergearticles where artid = @artid and pubid = @pubid set @artid = NULL select @artid = artid FROM sysmergearticles WHERE pubid = @pubid end fetch #RemoveReplication into @pubid end close #RemoveReplication deallocate #RemoveReplication /* Now clean up any traces in other system tables */ delete from MSmerge_genhistory delete from MSmerge_replinfo delete from sysmergesubsetfilters delete from sysmergesubscriptions delete from sysmergepublications delete from sysmergeschemachange return (0) GO exec dbo.sp_MS_marksystemobject sp_cleanupdbreplication go grant execute on dbo.sp_cleanupdbreplication to public go raiserror('Creating procedure sp_MSarticlecleanup', 0,1) GO create procedure sp_MSarticlecleanup (@pubid uniqueidentifier, @artid uniqueidentifier) as set nocount on declare @source_table nvarchar(270) declare @conflict_table nvarchar(270) declare @ownername sysname declare @objectname sysname declare @tablenick int declare @objid int declare @sync_objid int declare @view_type int declare @tsview nvarchar(50) declare @guidstr nvarchar(50) declare @csview nvarchar(50) declare @viewname nvarchar(270) declare @retcode smallint declare @qualified_name nvarchar(270) declare @bi_tablename sysname declare @bi_viewname sysname declare @bi_procname sysname declare @constraintname sysname declare @merge_pub_markcolumn_bit int declare @merge_pub_unmarkcolumn_bit int declare @bitableview sysname -- to be called after article is set up in a subscriber /* ** Security Check */ EXEC @retcode = dbo.sp_MSreplcheck_publish IF @@ERROR <> 0 or @retcode <> 0 return (1) select @merge_pub_markcolumn_bit = 0x4000 select @merge_pub_unmarkcolumn_bit = ~@merge_pub_markcolumn_bit select @objid = max(objid) from sysmergearticles where artid = @artid -- get owner name, and table name select @objectname = name, @ownername = user_name(uid) from sysobjects where id = @objid -- construct the qualified table name select @source_table = QUOTENAME(@ownername) + '.' + QUOTENAME(@objectname) exec @retcode=sp_MSguidtostr @artid, @guidstr out if @retcode<>0 or @@ERROR<>0 return (1) -- get the insert, update and conflict proc names from sysmergearticles select @sync_objid = sync_objid, @view_type = view_type, @tablenick = nickname, @bi_tablename = object_name(before_image_objid), @bi_viewname = object_name(before_view_objid), @conflict_table = conflict_table from sysmergearticles where pubid = @pubid and artid = @artid /* ** We are not owner_qualifed this conflict table because it is created by snapshot agent */ select @qualified_name = QUOTENAME(@ownername) + '.' + QUOTENAME(@conflict_table) /* Drop the conflict table */ if (@conflict_table IS NOT NULL) and exists (select * from sysobjects where name = @conflict_table and type = 'U') begin exec ('drop table ' + @qualified_name) if @@ERROR<>0 return (1) end /* If there is a before image table, drop it and its cleanup proc */ if (@bi_tablename is not null) begin set @bi_procname = @bi_tablename + '_clean' if exists (select * from sysobjects where name = @bi_procname and type = 'P') begin exec ('drop proc ' + @bi_procname) if @@ERROR<>0 return (1) end exec ('drop table ' + @bi_tablename) if @@ERROR<>0 return (1) end /* If there is a before image view, drop it */ if (@bi_viewname is not null) begin exec ('drop view ' + @bi_viewname) if @@ERROR<>0 return (1) end /* Drop the article procs */ exec @retcode=sp_MSdroparticleprocs @pubid, @artid if @@ERROR<>0 or @retcode<>0 return (1) /* Drop the article triggers */ exec @retcode=sp_MSdroparticletriggers @source_table if @@ERROR<>0 or @retcode<>0 return (1) exec @retcode=sp_MSunmarkreplinfo @objectname, @ownername if @@ERROR<>0 or @retcode<>0 return (1) /* so that columns can be dropped */ update syscolumns set colstat=colstat & @merge_pub_unmarkcolumn_bit where id=@objid if @@ERROR<>0 return (1) /* If the article's has a temporary ( view type = 2) or a permanent view (view_type = 1 ) drop the sync object */ if (@view_type = 1 OR @view_type = 2) begin select @viewname = sysobjects.name from sysobjects where ObjectProperty (sysobjects.id, 'IsView') = 1 and ObjectProperty (sysobjects.id, 'IsMSShipped') = 1 and sysobjects.id = @sync_objid if @viewname IS NOT NULL begin select @ownername = user_name(uid) from sysobjects where name=@viewname set @viewname = QUOTENAME(@ownername) + '.' + QUOTENAME(@viewname) exec ('drop view ' + @viewname) if @@ERROR<>0 return (1) end end /* ** Drop the views created for MSmerge_contents, MSmerge_tombstone and sysmergearticles before dropping these two tables */ set @csview = 'ctsv_' + @guidstr set @tsview = 'tsvw_' + @guidstr set @bitableview = 'MSbivw_' + @guidstr if EXISTS (select * from sysobjects where name=@csview and type='V') BEGIN select @ownername = user_name(uid) from sysobjects where name=@csview select @viewname = QUOTENAME(@ownername) + '.' + QUOTENAME(@csview) exec ('drop view ' + @viewname) if @@ERROR<>0 return (1) END if EXISTS (select * from sysobjects where name=@tsview and type='V') BEGIN select @ownername = user_name(uid) from sysobjects where name=@tsview select @viewname = QUOTENAME(@ownername) + '.' + QUOTENAME(@tsview) exec ('drop view ' + @viewname) if @@ERROR<>0 return (1) END if EXISTS (select * from sysobjects where name=@bitableview and type='V') BEGIN select @ownername = user_name(uid) from sysobjects where name=@bitableview select @viewname = QUOTENAME(@ownername) + '.' + QUOTENAME(@bitableview) exec ('drop view ' + @viewname) if @@ERROR<>0 return (1) END select @constraintname = 'repl_identity_range_pub_' + convert(nvarchar(36), @artid) select @constraintname = REPLACE(@constraintname, '-', '_') if exists (select * from sysobjects where name = @constraintname and xtype='C') begin exec ('alter table '+ @source_table + ' drop constraint ' + @constraintname) if @@ERROR<>0 return (1) end select @constraintname = 'repl_identity_range_repub_' + convert(nvarchar(36), @artid) select @constraintname = REPLACE(@constraintname, '-', '_') if exists (select * from sysobjects where name = @constraintname and xtype='C') begin exec ('alter table '+ @source_table + ' drop constraint ' + @constraintname) if @@ERROR<>0 return (1) end /* Delete from contents, tombstone, delete conflicts; Ignore errors that occur */ delete from MSmerge_contents where tablenick = @tablenick delete from MSmerge_tombstone where tablenick = @tablenick /* Delete rows from MSmerge_genhistory - if this is the last table that refers to them */ if not exists (select * from sysmergearticles where nickname = @tablenick and pubid <> @pubid) delete from MSmerge_genhistory where art_nick = @tablenick delete from MSmerge_delete_conflicts where tablenick = @tablenick delete from MSrepl_identity_range where objid=@objid GO exec dbo.sp_MS_marksystemobject sp_MSarticlecleanup go grant execute on dbo.sp_MSarticlecleanup to public go raiserror('Creating procedure sp_MSdroparticleprocs', 0,1) GO create procedure sp_MSdroparticleprocs (@pubid uniqueidentifier, @artid uniqueidentifier) as set nocount on declare @ins_procname sysname declare @upd_procname sysname declare @conf_procname sysname declare @sel_procname sysname declare @tmp_procname nvarchar(260) declare @view_sel_proc nvarchar(290) declare @owner sysname declare @objid int -- get the insert, update and conflict proc names from sysmergearticles select @ins_procname = insert_proc, @upd_procname = update_proc, @sel_procname = select_proc, @conf_procname = ins_conflict_proc, @view_sel_proc = view_sel_proc, @objid = objid from sysmergearticles where pubid = @pubid and artid = @artid if (@ins_procname IS NOT NULL) and exists (select * from sysobjects where name = @ins_procname and type = 'P') begin select @owner = user_name(uid) from sysobjects where name=@ins_procname select @tmp_procname = QUOTENAME(@owner) + '.' + QUOTENAME(@ins_procname) exec ('drop proc ' + @tmp_procname) if @@ERROR<>0 return (1) update sysmergearticles set insert_proc = NULL where pubid=@pubid and artid=@artid end if (@upd_procname IS NOT NULL) and exists (select * from sysobjects where name = @upd_procname and type = 'P') begin select @owner = user_name(uid) from sysobjects where name=@upd_procname select @tmp_procname = QUOTENAME(@owner) + '.' + QUOTENAME(@upd_procname) exec ('drop proc ' + @tmp_procname) if @@ERROR<>0 return (1) update sysmergearticles set update_proc = NULL where pubid=@pubid and artid=@artid end if (@sel_procname IS NOT NULL) and exists (select * from sysobjects where name = @sel_procname and type = 'P') begin select @owner = user_name(uid) from sysobjects where name=@sel_procname select @tmp_procname = QUOTENAME(@owner) + '.' + QUOTENAME(@sel_procname) exec ('drop proc ' + @tmp_procname) if @@ERROR<>0 return (1) update sysmergearticles set select_proc = NULL where pubid=@pubid and artid=@artid end if (@view_sel_proc IS NOT NULL) and exists (select * from sysobjects where name = @view_sel_proc and type = 'P') begin select @owner = user_name(uid) from sysobjects where name=@view_sel_proc select @tmp_procname = QUOTENAME(@owner) + '.' + QUOTENAME(@view_sel_proc) exec ('drop proc ' + @tmp_procname) if @@ERROR<>0 return (1) update sysmergearticles set view_sel_proc = NULL where pubid=@pubid and artid=@artid end if (@conf_procname IS NOT NULL) and not exists (select * from sysmergearticles where artid=@artid and pubid<>@pubid) and exists (select * from sysobjects where name = @conf_procname and type = 'P') begin select @owner = user_name(uid) from sysobjects where name=@conf_procname select @tmp_procname = QUOTENAME(@owner) + '.' + QUOTENAME(@conf_procname) exec ('drop proc ' + @tmp_procname) if @@ERROR<>0 return (1) update sysmergearticles set ins_conflict_proc = NULL where pubid=@pubid and artid=@artid end return 0 GO exec dbo.sp_MS_marksystemobject sp_MSdroparticleprocs go raiserror('Creating procedure sp_MSdroparticletriggers', 0,1) GO /* ** We need to qualify sysmergearticle with pubid */ create procedure sp_MSdroparticletriggers (@source_table nvarchar(270), @table_owner sysname = NULL) as set nocount on declare @instrigger nvarchar(270) declare @updtrigger nvarchar(270) declare @deltrigger nvarchar(270) declare @retcode int declare @owner sysname declare @artid uniqueidentifier declare @guidstr nvarchar(32) -- PARSENAME VARS declare @UnqualName sysname --rightmost name node declare @QualName1 sysname -- END PARSENAME VARS select @UnqualName = PARSENAME(@source_table, 1) select @QualName1 = PARSENAME(@source_table, 2) if @UnqualName IS NULL return 1 if @QualName1 is not NULL select @owner = @QualName1 else if @table_owner is not NULL select @owner = @table_owner else select @owner='dbo' select @artid = artid from sysmergearticles where objid = object_id(@source_table) exec @retcode=sp_MSguidtostr @artid, @guidstr out if @retcode<>0 or @@ERROR<>0 return (1) select @instrigger = QUOTENAME(@owner) + '.ins_' + @guidstr select @updtrigger = QUOTENAME(@owner) + '.upd_' + @guidstr select @deltrigger = QUOTENAME(@owner) + '.del_' + @guidstr /* select @instrigger = sysobjects.name from sysobjects where ObjectProperty (sysobjects.id, 'ExecIsInsertTrigger') = 1 and ObjectProperty (sysobjects.id, 'IsMSShipped') = 1 and parent_obj = OBJECT_ID(@source_table) select @updtrigger = sysobjects.name from sysobjects where ObjectProperty (sysobjects.id, 'ExecIsUpdateTrigger') = 1 and ObjectProperty (sysobjects.id, 'IsMSShipped') = 1 and parent_obj = OBJECT_ID(@source_table) select @deltrigger = sysobjects.name from sysobjects where ObjectProperty (sysobjects.id, 'ExecIsDeleteTrigger') = 1 and ObjectProperty (sysobjects.id, 'IsMSShipped') = 1 and parent_obj = OBJECT_ID(@source_table) */ if object_id(@instrigger) is not NULL begin exec ('drop trigger ' + @instrigger) if @@ERROR<>0 return (1) end if object_id(@updtrigger) is not NULL begin exec ('drop trigger ' + @updtrigger) if @@ERROR<>0 return (1) end if object_id(@deltrigger) IS NOT NULL begin exec ('drop trigger ' + @deltrigger) if @@ERROR<>0 return (1) end return 0 GO exec dbo.sp_MS_marksystemobject sp_MSdroparticletriggers go raiserror('Creating procedure sp_mergesubscription_cleanup', 0,1) GO CREATE PROCEDURE sp_mergesubscription_cleanup ( @publisher sysname, @publisher_db sysname, @publication sysname ) AS declare @pubid uniqueidentifier declare @artid uniqueidentifier declare @retcode smallint declare @subscription_type int declare @objid int declare @objectname sysname declare @objectowner sysname /* ** Security check */ EXEC @retcode = dbo.sp_MSreplcheck_subscribe IF @@ERROR <> 0 or @retcode <> 0 RETURN(1) /* ** if there is nothing to cleanup, then just return. */ if not exists (select * from sysobjects where name='sysmergesubscriptions') return (0) /* This only gets called after database is enable to subscribe, so sysmergepublications should exist */ select @pubid = pubid FROM sysmergepublications WHERE name = @publication and UPPER(publisher)=UPPER(@publisher) and publisher_db=@publisher_db /* Normal case - nothing to cleanup, just return */ if @pubid is null return (1) select @subscription_type = subscription_type from sysmergesubscriptions where pubid=@pubid and subid<>pubid /* This procedure is not intended to be used for cleanning-up pull/anonymous subscriptions */ if @subscription_type > 0 begin raiserror(20091, 16, -1) return (1) end /* Clean up the articles for this publication, and delete the row */ select @artid = artid FROM sysmergearticles WHERE pubid = @pubid while @artid is not null begin if not exists (select * from sysmergearticles WHERE artid = @artid and pubid <> @pubid) begin exec @retcode=sp_MSarticlecleanup @pubid, @artid if @retcode<>0 or @@ERROR<>0 return (1) end delete from sysmergearticles where artid = @artid and pubid = @pubid set @artid = NULL select @artid = artid FROM sysmergearticles WHERE pubid = @pubid end /* Cleanup the schema articles */ /* Unmark all schema article objects unconditionally */ if exists (select * from sysobjects where name = 'sysmergeschemaarticles') begin declare hschemaarticle_cur cursor local fast_forward for select destination_object, destination_owner from sysmergeschemaarticles where pubid = @pubid for read only open hschemaarticle_cur fetch hschemaarticle_cur into @objectname, @objectowner while (@@fetch_status<>-1) begin -- Ignore errors exec sp_MSunmarkschemaobject @objectname, @objectowner fetch hschemaarticle_cur into @objectname, @objectowner end close hschemaarticle_cur deallocate hschemaarticle_cur /* Delete all schema article rows for this publication*/ delete from sysmergeschemaarticles where pubid = @pubid end /* ** Make sure you NULL out gen_cur for other articles that share this table ** since we are deleting the genhistroy row for that generation */ update sysmergearticles set gen_cur=NULL where gen_cur in (select generation from MSmerge_genhistory where pubid = @pubid) /* Now clean up any traces in other system tables */ delete from MSmerge_genhistory where pubid = @pubid delete from MSmerge_replinfo where repid in (select subid from sysmergesubscriptions where pubid = @pubid) delete from sysmergesubscriptions where pubid = @pubid delete from sysmergepublications where pubid = @pubid delete from sysmergeschemachange where pubid = @pubid /* ** If last subscription is dropped and the DB is not enabled for publishing, ** then remove the merge system tables */ IF (not exists (select * from sysmergesubscriptions )) AND (select category & 4 FROM master..sysdatabases WHERE name = DB_NAME() collate database_default )=0 BEGIN execute @retcode = dbo.sp_MSdrop_mergesystables if @@ERROR <> 0 or @retcode <> 0 begin return (1) end END GO exec dbo.sp_MS_marksystemobject sp_mergesubscription_cleanup go grant execute on dbo.sp_mergesubscription_cleanup to public raiserror('Creating procedure sp_subscription_cleanup', 0,1) GO CREATE PROCEDURE sp_subscription_cleanup ( @publisher sysname, @publisher_db sysname, @publication sysname = NULL, @reserved nvarchar(10) = NULL ) AS BEGIN declare @object_name sysname ,@object_type char(2) ,@independent_agent bit ,@retcode int ,@synctran_bit int ,@parent_obj int ,@object_id int ,@cmd nvarchar(4000) select @synctran_bit = 256 /* ** Security Check */ EXEC @retcode = dbo.sp_MSreplcheck_subscribe IF @@ERROR <> 0 or @retcode <> 0 RETURN(1) if @publication = '' OR @publication is NULL select @independent_agent = 0 else select @independent_agent = 1 IF exists (select name from sysobjects where name = 'MSreplication_objects') BEGIN declare object_cursor CURSOR LOCAL FAST_FORWARD for select DISTINCT object_name, object_type from MSreplication_objects o where (UPPER(o.publisher) = UPPER(@publisher) and o.publisher_db = @publisher_db and o.publication = @publication) or @reserved = 'drop_all' OPEN object_cursor FETCH object_cursor INTO @object_name, @object_type WHILE (@@fetch_status <> -1) BEGIN IF @object_type = 'T' begin select @parent_obj = NULL select @parent_obj = parent_obj, @object_id = id from sysobjects where name = @object_name if @parent_obj is not null begin -- Unmark synctran bit update sysobjects set replinfo = replinfo & ~@synctran_bit where id = @parent_obj and (replinfo & @synctran_bit) <> 0 IF @@ERROR <> 0 GOTO UNDO exec @retcode = dbo.sp_MSdrop_object @object_id = @object_id if @retcode <> 0 or @@error <> 0 goto UNDO -- Clean up identity range entry -- Since we only support one trigger per subscriber table -- we assume identity range row can not be reused by multiple -- subscriptions. IF EXISTS(select * from sysobjects where type='U' and name = 'MSsub_identity_range') BEGIN if exists (select * from MSsub_identity_range where objid = @parent_obj) begin -- Drop the identity range constraits. exec @retcode = dbo.sp_MSreseed @objid = @parent_obj, -- range or seed can be anything @next_seed = 10, @range = 10, @is_publisher = -1, @check_only = 1, @drop_only = 1 IF @retcode <> 0 or @@ERROR <> 0 GOTO UNDO delete MSsub_identity_range where objid = @parent_obj IF @@ERROR <> 0 GOTO UNDO end IF NOT EXISTS (SELECT * FROM MSsub_identity_range) BEGIN DROP TABLE MSsub_identity_range IF @@ERROR <> 0 GOTO UNDO END END end end delete from MSreplication_objects where object_name=@object_name FETCH object_cursor INTO @object_name, @object_type END CLOSE object_cursor DEALLOCATE object_cursor if not exists (select * from MSreplication_objects) begin drop table MSreplication_objects IF @@ERROR <> 0 GOTO UNDO end END -- -- cleanup queued conflict tables -- IF exists (select name from dbo.sysobjects where name = 'MSsubscription_agents') BEGIN declare @agent_id int ,@cft_table sysname ,@owner sysname -- -- first get the agent(s) for this queued subscription(s) and -- declare #agent_cursor CURSOR LOCAL FAST_FORWARD for select id from dbo.MSsubscription_agents where ((UPPER(publisher) = UPPER(@publisher) and publisher_db = @publisher_db and publication = @publication) or (@reserved = 'drop_all')) and update_mode in (2,3,4,5) open #agent_cursor fetch #agent_cursor into @agent_id while (@@fetch_status != -1) begin -- -- drop the conflict table for each article in this subscription -- if exists (select name from dbo.sysobjects where name = 'MSsubscription_articles') begin declare #object_cursor CURSOR LOCAL FAST_FORWARD for select owner, cft_table from dbo.MSsubscription_articles where agent_id = @agent_id OPEN #object_cursor FETCH #object_cursor INTO @owner, @cft_table WHILE (@@fetch_status != -1) BEGIN -- -- drop the conflict table(s) for this article - ignore errors -- select @cmd = case when (@owner IS NULL) then N'if exists (select * from dbo.sysobjects where name = N''' + master.dbo.fn_MSgensqescstr(@cft_table) collate database_default + ''') drop table ' + quotename(master.dbo.fn_MSgensqescstr(@cft_table)) collate database_default else N'if exists (select * from dbo.sysobjects where name = N''' + master.dbo.fn_MSgensqescstr(@cft_table) collate database_default + ''') drop table ' + quotename(master.dbo.fn_MSgensqescstr(@owner)) collate database_default + N'.' + quotename(master.dbo.fn_MSgensqescstr(@cft_table)) collate database_default end execute ( @cmd ) -- get next row FETCH #object_cursor INTO @owner, @cft_table END CLOSE #object_cursor DEALLOCATE #object_cursor -- -- delete entries from MSsubscription_articles for this agent id -- delete dbo.MSsubscription_articles where agent_id = @agent_id -- -- drop MSsubscription_articles if empty (should we do it) -- IF NOT EXISTS (SELECT * FROM dbo.MSsubscription_articles) BEGIN DROP TABLE dbo.MSsubscription_articles IF @@ERROR != 0 GOTO UNDO END end -- -- get the next agent -- fetch #agent_cursor into @agent_id end close #agent_cursor deallocate #agent_cursor END -- -- clean discarded queued transactions -- if exists (select name from dbo.sysobjects where name = 'MSreplication_queue') begin delete dbo.MSreplication_queue where (publisher = UPPER(@publisher) and publisher_db = @publisher_db and publication = @publication) or @reserved = 'drop_all' end if exists (select name from dbo.sysobjects where name = 'MSrepl_queuedtraninfo') begin delete dbo.MSrepl_queuedtraninfo where (publisher = UPPER(@publisher) and publisher_db = @publisher_db and publication = @publication) or @reserved = 'drop_all' end IF exists (select name from sysobjects where name = 'MSreplication_subscriptions') BEGIN delete from MSreplication_subscriptions where (UPPER(publisher) = UPPER(@publisher) AND publisher_db = @publisher_db AND -- Drop the subscription as long as the publication name matches even if -- the publication is not independent agent -- This behaviour is expected by sp_droppullsubscription -- -- independent_agent = @independent_agent and ((@independent_agent=0 and independent_agent = 0) or publication = @publication)) or @reserved = 'drop_all' IF NOT EXISTS (SELECT * FROM MSreplication_subscriptions) BEGIN DROP TABLE MSreplication_subscriptions IF @@ERROR <> 0 GOTO UNDO END END IF exists (select name from sysobjects where name = 'MSsubscription_agents') BEGIN delete from MSsubscription_agents where (UPPER(publisher) = UPPER(@publisher) AND publisher_db = @publisher_db AND -- Drop the subscription as long as the publication name matches even if -- the publication is not independent agent -- This behaviour is expected by sp_droppullsubscription (publication = @publication or (@independent_agent=0 and publication = N'ALL'))) or @reserved = 'drop_all' -- Delete the agent entry if no corresponding rows found in MSreplication_subscription -- table. -- This is to cleanup share agent entry. -- This behaviour is expected by sp_droppullsubscription if object_id('MSreplication_subscriptions') is not null begin if not exists (select * from MSreplication_subscriptions s where s.publisher = @publisher and s.publisher_db = @publisher_db and s.independent_agent = 0) delete from MSsubscription_agents where publisher = @publisher and publisher_db = @publisher_db and publication = N'ALL' end else delete MSsubscription_agents IF NOT EXISTS (SELECT * FROM MSsubscription_agents) BEGIN DROP TABLE MSsubscription_agents IF @@ERROR <> 0 GOTO UNDO END END IF EXISTS(select * from sysobjects where type=N'U' and name = 'MSsubscription_properties') BEGIN DELETE FROM MSsubscription_properties WHERE (UPPER(publisher) = UPPER(@publisher) AND publisher_db = @publisher_db AND publication = @publication) or @reserved = 'drop_all' IF @@ERROR <> 0 GOTO UNDO IF NOT EXISTS (SELECT * FROM MSsubscription_properties) BEGIN exec @retcode = dbo.sp_MSsub_cleanup_prop_table IF @@ERROR <> 0 or @retcode <> 0 GOTO UNDO END END -- Ignore errors. exec dbo.sp_MSsub_cleanup_orphans return (0) UNDO: return(1) END GO exec dbo.sp_MS_marksystemobject sp_subscription_cleanup go raiserror('Creating procedure sp_get_distributor', 0,1) go -- Called by the UI to find out if the distributor is installed without doing RPC. CREATE PROCEDURE sp_get_distributor AS SET NOCOUNT ON /* ** Declarations. */ DECLARE @distributor sysname DECLARE @installed bit declare @distdb_installed bit declare @is_distpublisher bit declare @has_remote_distpublisher bit declare @distbit int SELECT @distbit = 16 SELECT @distributor = datasource FROM master..sysservers WHERE srvstatus & 8 <> 0 if @distributor is not null select @installed = 1 else select @installed = 0 if UPPER(@distributor) = UPPER(@@servername) begin if exists (select * from msdb.dbo.MSdistributiondbs) select @distdb_installed = 1 else select @distdb_installed = 0 if exists (select * from msdb..MSdistpublishers where UPPER(name) = UPPER(@@servername) collate database_default) select @is_distpublisher = 1 else select @is_distpublisher = 0 if exists (select * from msdb..MSdistpublishers where UPPER(name) <> UPPER(@@servername) collate database_default) select @has_remote_distpublisher = 1 else select @has_remote_distpublisher = 0 end else begin select @distdb_installed = 0 select @has_remote_distpublisher = 0 select @is_distpublisher = 0 end select 'installed' = @installed, 'distribution server' = @distributor, 'distribution db installed' = @distdb_installed, 'is distribution publisher' = @is_distpublisher, 'has remote distribution publisher' = @has_remote_distpublisher GO exec dbo.sp_MS_marksystemobject sp_get_distributor go -- Called by sp_addrolemember raiserror('Creating procedure sp_MSrepl_addrolemember', 0,1) go CREATE PROCEDURE sp_MSrepl_addrolemember @rolename sysname, @membername sysname AS -- SETUP RUNTIME OPTIONS / DECLARE VARIABLES -- set nocount on return(0) go exec dbo.sp_MS_marksystemobject sp_MSrepl_addrolemember go -- Called by sp_droprolemember raiserror('Creating procedure sp_MSrepl_droprolemember', 0,1) go CREATE PROCEDURE sp_MSrepl_droprolemember @rolename sysname, @membername sysname AS set nocount on return(0) go exec dbo.sp_MS_marksystemobject sp_MSrepl_droprolemember go raiserror('Creating procedure sp_table_validation', 0,1) go create procedure sp_table_validation @table sysname, -- table name or sync object name @expected_rowcount bigint = NULL OUTPUT, @expected_checksum numeric = NULL OUTPUT, @rowcount_only smallint = 1, /* The @rowcount_only param is overloaded for shiloh release due to backward compatibility concerns. In shiloh, the checksum functionality has changed. So 7.0 subscribers will have the old checksum routines, which generate different CRC values, and do not have functionality for vertical partitions, or logical table structures where column offsets differ (due to ALTER TABLEs that DROP and ADD columns). In 7.0, this was a bit column. 0 meant do not do just a rowcount - do a checksum. 1 meant just do a rowcount. For Shiloh, this parameter is changed to a smallint. The name "rowcount_only" is now a misnomer given the overloaded functionality. It is really a "type of check requested" parameter. But, the old name is retained for backward compatibility. It can take these values: 0 - Do a 7.0 compatible checksum 1 - Do a rowcount check only (remains the default) 2 - Use new Shiloh checksum functionality. Note that because 7.0 subscribers will take this parameter as a bit type, not a smallint, it will be interpreted as simply ON. That means that passing a 2, and having a 7.0 subscriber, will result in the 7.0 subscriber doing only rowcount validation. The Shiloh subscribers will do both rowcount and checksum. If you want 7.0 subscribers to do checksum validation, use the value of 0 for this parameter. Shiloh subscribers can do the 7.0 compatible checksum, but that checksum has the same 7.0 limitations for vertical partitions and differences in physical table structure.) */ @owner sysname = NULL, @full_or_fast tinyint = 2, -- full (value 0) does COUNT(*) -- fast (value 1) uses sysindexes.rowcnt if table (not view); -- conditional fast (VALUE 2) , first tries fast method, but -- reverts to full if fast method shows differences. @shutdown_agent bit = 0, -- If 1 will raise error 20578, which will signal replication agent to shutdown @table_name sysname = NULL, -- table name of sync object or the table name for output message, @column_list nvarchar(4000) = NULL -- the list of columns - that way the user can skip computed columns etc as set nocount on declare @num_rows bigint declare @checksum numeric declare @checksum_string varchar(100) declare @expected_checksum_string varchar(21) declare @rowcount_string varchar(21) declare @exp_rowcount_string varchar(21) declare @width int declare @qualified_table_name nvarchar(262) -- two names plus []'s and a . declare @temp_table_used bit declare @retstatus int declare @failed_fast tinyint declare @min_indid int declare @asked_for_exp_checksum tinyint declare @asked_for_exp_rows tinyint SET @retstatus=0 -- initialize to SUCCESS SET @failed_fast=0 if (@expected_checksum IS NULL AND isnull(@rowcount_only,-9999) <> 1 ) -- Wants an expected checksum value SET @asked_for_exp_checksum=1 ELSE SET @asked_for_exp_checksum=0 if (@expected_rowcount IS NULL) -- Wants an expected rowcount value SET @asked_for_exp_rows=1 ELSE SET @asked_for_exp_rows=0 -- Only values 0,1,2 make sense for @rowcount_only. if (@rowcount_only NOT BETWEEN 0 and 2) BEGIN -- msg 20543 says that @rowcount_only must be 0,1,2 and explains the values. RAISERROR (20543,16,-1,@qualified_table_name) SET @retstatus=1 return @retstatus END -- RHS: -- Some states do not make sense. For example, it does not make sense to ask for conditional -- fast row count checking, yet not provide an expected value. If this is done, provide a warning -- message and use fast checking method. if (@full_or_fast = 2 AND @expected_rowcount IS NULL) BEGIN -- (20559,10,0,'Conditional Fast Rowcount method requested without specifying an expected count. Fast method will be used.', 1033) raiserror (20559, 10, -1) SET @full_or_fast = 1 END -- Another state that doesn't make sense is to pass an expected checksum value, yet -- ask for rowcount only validation if (@expected_checksum IS NOT NULL AND @rowcount_only = 1) BEGIN -- (Msg 20560,10,0,'An expected checksum value was passed, but checksums will not be compared because rowcount only checking was requested.', 1033) raiserror (20560, 10, -1) SET @expected_checksum = NULL END if @owner is null begin if left(ltrim(rtrim(@table)), 1) <> '[' or right(ltrim(rtrim(@table)), 1) <> ']' set @qualified_table_name = '[' + @table + ']' else set @qualified_table_name = @table end else begin if left(ltrim(rtrim(@table)), 1) <> '[' or right(ltrim(rtrim(@table)), 1) <> ']' set @qualified_table_name = '[' + @owner + '].[' + @table + ']' else set @qualified_table_name = '[' + @owner + '].' + @table end IF (OBJECT_ID(@qualified_table_name) IS NULL) -- No such object. Return with error. BEGIN -- Msg (20585,10,0,'Object '%s' does not exist. Exiting validation check.', 1033) RAISERROR (20585,16,-1,@qualified_table_name) SET @retstatus=1 return @retstatus END -- If the object is a table (not view) and fast checking (1) requested, -- then get rowcount from sysindexes, rather than scanning. -- Fast rowcount method gets value from sysindexes - and the row_cnt value is only maintained for tables. IF (SELECT @full_or_fast) > 0 -- IF Fast row checking asked for AND (SELECT OBJECTPROPERTY(OBJECT_ID(@qualified_table_name),'IsTable')) > 0 -- Must be a table, not a view BEGIN -- Do the fast rowcount method -- Temporarily put a SHARE lock on table to ensure no simultaneous updates going on -- Minimizes chances of getting an out of date value from sysindexes. True that -- it reduces concurrency, but if the fast method doesnt work the user will very likely -- go do the full method, which will be much more costly. Better I think to take a little more cost here -- and hopefully get a good number. The @foo variable is used so that its an -- assignment and doesn't make another result set get returned. BEGIN TRAN EXEC ('DECLARE @foo int SELECT @foo=1 FROM ' + @qualified_table_name + ' (TABLOCK HOLDLOCK) WHERE 1=2') SELECT @num_rows=rowcnt,@min_indid=indid FROM sysindexes WHERE id=OBJECT_ID(@qualified_table_name)and indid < 2 COMMIT TRAN END ELSE SET @full_or_fast = 0 -- Full checking will be used, regardless of whether it was requested -- set the output name if not set if (@table_name IS NULL) SELECT @table_name = @table -- If fast row checking was used, and request for rowcount check only, we're done. if (@full_or_fast = 1 AND @rowcount_only = 1) GOTO ROWCOUNT_MSG -- If conditional fast row checking was used, and request for rowcount check only, -- we're also done IFF rows and expected rows match. if (@full_or_fast = 2 AND @rowcount_only = 1 AND @expected_rowcount IS NOT NULL AND @expected_rowcount=@num_rows) BEGIN -- Fast checking was actually used. SET @full_or_fast = 1 GOTO ROWCOUNT_MSG END -- If we're still here we are doing full row checking at a minimum, and will need the temp table IF (SELECT ISNULL(OBJECT_ID('tempdb..#tab_validt1'),0)) = 0 -- Table Does Not exist CREATE TABLE #tab_validt1 (tmp_rows bigint NULL, tmp_checksum numeric NULL) ELSE -- table already exists TRUNCATE TABLE #tab_validt1 -- If we are only doing row checking, we'll do it here. If we will do both row checking -- and checksum, then do them together so as to not scan table twice. if @rowcount_only = 1 BEGIN -- Must do full count(*) checking but not checksums if @full_or_fast=2 -- if we are here with conditional check (2) requested, it is because -- a conditional was possible, but it failed. We wiil later alert user of this. BEGIN SET @full_or_fast=0 SET @failed_fast=1 END insert into #tab_validt1 (tmp_rows,tmp_checksum) exec ('select count_big(*), NULL from ' + @qualified_table_name + ' (TABLOCK HOLDLOCK)') -- Get row count value select TOP 1 @num_rows = tmp_rows from #tab_validt1 -- Should only be one row -- IF there were no rows from above, the table was empty so use ZERO. IF @num_rows IS NULL SELECT @num_rows=0 -- Done with the temp table DROP TABLE #tab_validt1 IF @expected_rowcount IS NULL BEGIN SET @expected_rowcount = @num_rows END GOTO ROWCOUNT_MSG END -- Done with full row count only ELSE -- Doing checksums in addition to ROWCOUNT BEGIN -- DO checksum and rowcount in same pass thru the table -- Decide whether must use the 7.0 compatible checksum, or use the Shiloh checksum: IF (@rowcount_only = 0) -- 7.0 Compatible Checksum BEGIN insert into #tab_validt1 (tmp_rows,tmp_checksum) exec ('select count_big(*), sum (convert(numeric, getchecksum(NULL,1))) from ' + @qualified_table_name + ' (TABLOCK HOLDLOCK)') END ELSE BEGIN -- Shiloh Checksum if @column_list IS NULL OR @column_list = ' * ' begin insert into #tab_validt1 (tmp_rows,tmp_checksum) exec ('select count_big(*), sum (convert(numeric, binary_checksum(*) ) ) from ' + @qualified_table_name + ' (TABLOCK HOLDLOCK)') end else begin insert into #tab_validt1 (tmp_rows,tmp_checksum) exec ('select count_big(*), sum (convert(numeric, binary_checksum( ' + @column_list + ') ) ) from ' + @qualified_table_name + ' (TABLOCK HOLDLOCK)') end END -- Get the checksum & rowcount values select TOP 1 @checksum = tmp_checksum, @num_rows= tmp_rows from #tab_validt1 -- IF there were no rows from above, the table was empty so use ZERO. IF @checksum IS NULL or @num_rows IS NULL SELECT @checksum=isnull(@checksum,0),@num_rows=isnull(@checksum,0) -- Done with the temp table DROP TABLE #tab_validt1 IF @expected_rowcount IS NULL -- Just getting value - no expected value yet. SET @expected_rowcount = @num_rows -- Validate checksum IF @expected_checksum is null -- Just getting value - no expected value yet. set @expected_checksum = @checksum else -- Raise error if checksums OR rowcounts do not match if @checksum <> @expected_checksum OR @num_rows <> @expected_rowcount begin -- Checksum failed. SELECT @checksum_string = convert(varchar(21), @checksum), @expected_checksum_string = convert(varchar(21), @expected_checksum), @rowcount_string = convert(varchar(21),@num_rows), @exp_rowcount_string = convert(varchar(21),@expected_rowcount) -- Msg (20525,10,0,'Table ''%s'' might be out of synchronization. Rowcounts (actual: %s, expected %s). Checksum values (actual: %s, expected: %s).', 1033) raiserror (20525, 10, -1, @table, @rowcount_string, @exp_rowcount_string, @checksum_string, @expected_checksum_string) SET @retstatus=1 END else BEGIN -- Row count and checksum validation passed. -- if @asked_for_exp_checksum=0 -- Only give message if not generating the expected value BEGIN -- Msg (20527,10,0,'Table ''%s'' passed rowcount (%s) and checksum validation. (Note: checksum is not compared for any text and image columns.)', 1033) SET @rowcount_string=convert(varchar(21),@num_rows) raiserror (20527, 10, -1, @table,@rowcount_string) END END -- Done with checksum and rowcount scan. END -- We did checksum method, and so are done and skip over the rowcount only messages. GOTO ALL_DONE ROWCOUNT_MSG: -- Raise error if rows counts do not match IF @expected_rowcount IS NULL -- just return the found value SET @expected_rowcount=@num_rows ELSE IF @num_rows <> @expected_rowcount begin SELECT @rowcount_string=convert(varchar(21),@num_rows), @exp_rowcount_string=convert(varchar(21),@expected_rowcount) -- Msg (20524,10,0,'Table ''%s'' may be out of synchronization. Rowcounts (actual: %s, expected: %s). Rowcount method %d used (0 = Full, 1 = Fast).', 1033) raiserror (20524, 10, -1, @table_name, @rowcount_string, @exp_rowcount_string, @full_or_fast ) SET @retstatus=1 end ELSE -- Row count validation passed. begin SET @rowcount_string=convert(varchar(21),@num_rows) if @asked_for_exp_rows=0 -- Only give message if not generating the expected value -- Msg (20526,10,0,'Table ''%s'' passed rowcount (%s) validation. Rowcount method %d used (0 = Full, 1 = Fast).', 1033) raiserror (20526, 10, -1, @table_name, @rowcount_string, @full_or_fast) if @failed_fast=1 BEGIN -- if we had to revert to FULL on a CONDITIONAL FAST, Make that known too. -- And Update usage to fix the problem -- Msg 20558: 'Table ''%s'' passed full row count validation after failing the fast check. DBCC UPDATEUSAGE will be automatically initiated.' raiserror (20558, 10, -1, @table_name) DBCC UPDATEUSAGE (0,@qualified_table_name,@min_indid) WITH COUNT_ROWS, NO_INFOMSGS END end ALL_DONE: -- Give nice message if only generating the expected value: -- Msg for rows and checksum: -- TEMPORARY: Remove rowcount string & change message if/when RAISERROR can handle bigint directly. SET @rowcount_string = convert(varchar(21),@expected_rowcount) if @asked_for_exp_checksum=1 and @asked_for_exp_rows=1 -- Only give message if generating the expected value BEGIN SET @expected_checksum_string = convert(varchar(21), @expected_checksum) -- (20579,10,0,'Generated expected rowcount value of %s and expected checksum value of %s for %s.', 1033) RAISERROR (20579, 10, -1,@rowcount_string,@expected_checksum_string,@table_name) END ELSE BEGIN if @asked_for_exp_checksum=0 and @asked_for_exp_rows=1 -- Msg (20561,10,0,'Generated expected rowcount value of %s for %s.', 1033) raiserror (20561, 10, -1,@rowcount_string, @table_name) END -- Raise error that will shutdown replication agents if @shutdown_agent = 1 --Msg 20578: 'Shutdown replication agent request.' raiserror (20578, 10, -1) return @retstatus go exec dbo.sp_MS_marksystemobject sp_table_validation go /* Create sp_removedbreplication */ raiserror('Creating procedure sp_removedbreplication', 0,1) GO /* Permission to sysadmin */ CREATE PROCEDURE sp_removedbreplication ( @dbname sysname ) AS SET NOCOUNT ON /* ** Declarations. */ DECLARE @retcode int DECLARE @proc nvarchar(255) DECLARE @optbit int DECLARE @restoreoverride int /* ** Initialization */ /* ** Support override of replication remove on attach and restore */ declare @instance sysname declare @regkey nvarchar(260) select @instance = convert(sysname, SERVERPROPERTY('InstanceName')) select @regkey = 'SOFTWARE\Microsoft\' -- default installation if @instance is null SELECT @regkey = @regkey + 'MSSQLServer\Replication' else SELECT @regkey = @regkey + 'Microsoft SQL Server\' + @instance + '\Replication' SELECT @restoreoverride = 0 -- assume normal remove behavior SELECT @proc = 'master.dbo.xp_regread ' EXECUTE @retcode = @proc 'HKEY_LOCAL_MACHINE', @regkey, 'RestoreOverride', @param = @restoreoverride OUTPUT, @no_output = 'no_output' IF ( @@error = 0 ) and ( @retcode = 0 ) BEGIN -- ReplRestoreOverride = 1 = user elects to take no cleanup on restore or attach IF ( ISNULL( @restoreoverride, 0 ) = 1 ) RETURN(0) END /* ** Parameter check ** @dbname */ IF NOT EXISTS (SELECT * FROM master.dbo.sysdatabases WHERE name = @dbname collate database_default) BEGIN RAISERROR(15010, 16, -1, @dbname) RETURN(1) END SELECT @proc = quotename(@dbname) + '.dbo.sp_MSremovedbreplication' EXEC @retcode = @proc IF @@ERROR <> 0 or @retcode <> 0 BEGIN return (1) END -- Clear tran bit SELECT @optbit = 1 IF EXISTS (SELECT * FROM master..sysdatabases WHERE name = @dbname collate database_default AND (category & @optbit) <> 0) begin /* ** Toggle the category bit in master..sysdatabases */ UPDATE master..sysdatabases SET category = category & ~@optbit WHERE name = @dbname collate database_default IF @@ERROR <> 0 BEGIN return (1) END end -- Clear merge bit SELECT @optbit = 4 IF EXISTS (SELECT * FROM master..sysdatabases WHERE name = @dbname collate database_default AND (category & @optbit) <> 0) begin /* ** Toggle the category bit in master..sysdatabases */ UPDATE master..sysdatabases SET category = category & ~@optbit WHERE name = @dbname collate database_default IF @@ERROR <> 0 BEGIN return (1) END end GO exec dbo.sp_MS_marksystemobject sp_removedbreplication go raiserror('Creating procedure sp_removesrvreplication', 0,1) GO create procedure sp_removesrvreplication as begin /* * unmark replication bits for all servers, databases; used by setup in vupgrade * assumes override is on; db in single user mode * no need to check rowcounts affected by updates, may not be any repl dbs * failure label avoids repetition of errs if not in single user mode */ set nocount on -- server bits declare @srv_distbit int declare @srv_pubbit int declare @srv_subbit int declare @srv_dsnbit int select @srv_distbit = 8, @srv_pubbit = 16, @srv_subbit = 4, @srv_dsnbit = 32 -- dsn subscriber -- db bits declare @db_tranbit int declare @db_mergbit int declare @db_distbit int select @db_tranbit = 1, @db_mergbit = 4, @db_distbit = 16 -- setup attach overrides removedb option declare @dbname sysname declare cur_db CURSOR LOCAL FAST_FORWARD for select name from master..sysdatabases where name <> N'master' collate database_default for read only open cur_db fetch cur_db into @dbname while ( @@fetch_status <> -1 ) begin exec dbo.sp_removedbreplication @dbname -- clean up system tables exec ( @dbname + '.dbo.sp_MSdrop_pub_tables' ) exec ( @dbname + '.dbo.sp_MSdrop_mergesystables' ) fetch next from cur_db into @dbname end close cur_db deallocate cur_db -- unmark db bits -- select name, category from sysdatabases where category & @tranbit = @tranbit update master..sysdatabases set category = category & ~@db_tranbit where category & @db_tranbit = @db_tranbit if @@ERROR <> 0 goto fail update master..sysdatabases set category = category & ~@db_mergbit where category & @db_mergbit = @db_mergbit if @@ERROR <> 0 goto fail -- clean up old dist db bit update master..sysdatabases set category = category & ~@db_distbit where category & @db_distbit = @db_distbit if @@ERROR <> 0 goto fail -- unmark srv bits (srvstatus = @dsnbit no longer used by replication subscribers but by server ) -- select name, srvstatus from sysservers where srvstatus & @srv_distbit = @srv_distbit update master..sysservers set srvstatus = srvstatus & ~@srv_subbit where srvstatus & @srv_subbit = @srv_subbit if @@ERROR <> 0 goto fail update master..sysservers set srvstatus = srvstatus & ~@srv_pubbit where srvstatus & @srv_pubbit = @srv_pubbit if @@ERROR <> 0 goto fail update master..sysservers set srvstatus = srvstatus & ~@srv_distbit where srvstatus & @srv_distbit = @srv_distbit if @@ERROR <> 0 goto fail return (0) fail: -- ad hoc updates not allowed and not single user return (1) end go exec dbo.sp_MS_marksystemobject sp_removesrvreplication go raiserror('Creating procedure sp_MSremovedbreplication', 0,1) GO CREATE PROCEDURE sp_MSremovedbreplication AS SET NOCOUNT ON /* ** Declarations. */ DECLARE @retcode int -- If the attach info table exists, we need to restore the subscriptions, not -- deleting anything. Do nothing. if exists (select * from sysobjects where name = 'MSreplication_restore_stage') return 0 if exists (select * from sysobjects where name = 'sysarticles') -- clean up transactional begin if not exists (select * from master..MSreplication_options where optname = 'transactional') begin RAISERROR(21027, 16, -1, 'transactional') return(1) end EXEC @retcode = dbo.sp_MSpublishdb @value = 'false', @ignore_distributor = 1 IF @@ERROR <> 0 or @retcode <> 0 BEGIN return (1) END end if exists (select * from sysobjects where name = 'sysmergearticles') -- clean up merge -- can not use sp_MSmergepublishdb or sp_dropmergepullsubscriptions -- since they depend on serverid and dbname begin declare @pubid uniqueidentifier declare @artid uniqueidentifier declare hC CURSOR LOCAL FAST_FORWARD FOR select DISTINCT pubid, artid FROM sysmergearticles FOR READ ONLY OPEN hC FETCH hC INTO @pubid, @artid WHILE (@@fetch_status <> -1) begin EXEC @retcode = dbo.sp_MSarticlecleanup @pubid, @artid IF @@ERROR <> 0 or @retcode <> 0 BEGIN return (1) end FETCH hC INTO @pubid, @artid end execute @retcode = dbo.sp_MSdrop_mergesystables if @@ERROR <> 0 or @retcode <> 0 begin return (1) end end if exists (select * from sysobjects where name = 'MSreplication_subscriptions') -- clean up tran sub begin -- drop pull subscription EXEC @retcode = dbo.sp_droppullsubscription @publisher = N'all', @publisher_db = N'all', @publication = N'all' IF @@ERROR <> 0 or @retcode <> 0 BEGIN return (1) END -- drop push subscription EXEC @retcode = dbo.sp_subscription_cleanup @publisher = N'all', @publisher_db = N'all', @publication = N'all', @reserved = 'drop_all' IF @@ERROR <> 0 or @retcode <> 0 BEGIN return (1) END end GO exec dbo.sp_MS_marksystemobject sp_MSremovedbreplication go raiserror('Creating procedure sp_vupgrade_subscription_databases', 0,1) GO create procedure sp_vupgrade_subscription_databases as begin /* * Process schema and metadata changes common to all databases. This proc loops * through each database and upgrades MSsubscription_properties, transactional tables * and merge tables. * * Setup version upgrade procedure call order: * sp_vupgrade_replication -> sp_vupgrade_subscription_databases */ set nocount on -- raiserror('sp_vupgrade_subscription_databases', 0,1) with nowait declare @dbname nvarchar(270), @has_dbaccess bit declare current_db CURSOR LOCAL FAST_FORWARD for select N'[' + replace(name, N']', N']]') + N']', has_dbaccess(name) from master..sysdatabases WHERE name <> N'master' collate database_default AND name <> N'tempdb' collate database_default AND name <> N'msdb' collate database_default for read only -- Note: dbname is quoted! open current_db fetch current_db into @dbname, @has_dbaccess while ( @@fetch_status <> -1 ) begin -- upgrade repl tables in sub dbs if needed - sub dbs are not marked with subscribed status -- skip any database in an offline state and write warning to upgrade log if ( @has_dbaccess = 1 ) begin -- -- NOTE : there are several things to process here -- for each upgrade - all these steps may NOT be necessary -- and should be commented/uncommented out as required -- -- Current setting for SQL 2000 SP1 upgrade -- raiserror( 21377, 0, 1, @dbname) with nowait -- exec ('use '+ @dbname + ' exec dbo.sp_vupgrade_MSsubscription_properties') exec ('use '+ @dbname + ' exec dbo.sp_vupgrade_subscription_tables') exec ('use '+ @dbname + ' exec dbo.sp_vupgrade_mergetables') -- exec ('use '+ @dbname + ' exec dbo.sp_vupgrade_subpass') end else begin raiserror( 21373, 10, 1, @dbname) with nowait end fetch next from current_db into @dbname, @has_dbaccess end close current_db deallocate current_db end go raiserror('Creating procedure sp_MScopyregvalue', 0,1) GO create procedure sp_MScopyregvalue( @oldregkey nvarchar(1000), @newregkey nvarchar(1000), @param_type nvarchar(20), @param_name sysname) as set nocount on declare @retcode int create table #binaryvalues ( value sysname collate database_default, data varbinary(256)) if (@param_type = 'REG_SZ') begin declare @value_str nvarchar(1000) set @value_str = NULL -- Read value from old reg location and write to new one EXECUTE @retcode = master.dbo.xp_regread 'HKEY_LOCAL_MACHINE', @oldregkey, @param_name, @param = @value_str OUTPUT, @no_output = 'no_output' if @retcode <> 0 or @@ERROR <> 0 begin set @retcode = 0 goto FAILURE end EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE', @newregkey, @param_name, 'REG_SZ', @value_str if @retcode <> 0 OR @@ERROR <> 0 begin set @retcode = 1 goto FAILURE end end if (@param_type = 'REG_DWORD') begin declare @value_int int set @value_int = NULL -- Read value from old reg location and write to new one EXECUTE @retcode = master.dbo.xp_regread 'HKEY_LOCAL_MACHINE', @oldregkey, @param_name, @param = @value_int OUTPUT, @no_output = 'no_output' if @retcode <> 0 or @@ERROR <> 0 begin set @retcode = 0 goto FAILURE end EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE', @newregkey, @param_name, 'REG_DWORD', @value_int if @retcode <> 0 OR @@ERROR <> 0 begin set @retcode = 1 goto FAILURE end end if (@param_type = 'REG_BINARY') begin declare @value_binary varbinary(256) set @value_binary = NULL -- Read value from old reg location and write to new one /* -- binary output buffer was corrupted for a couple of builds;looks to be working now -- if reverting to this read, must pre-check exists on regkey to avoid regopenkey failure -- on non-existent key when no OUTPUT parm specified insert into #binaryvalues EXECUTE master.dbo.xp_regread 'HKEY_LOCAL_MACHINE', @oldregkey, @param_name if @@ERROR <> 0 begin set @retcode = 0 goto FAILURE end select @value_binary = data from #binaryvalues if @value_binary is NOT NULL EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE', @newregkey, @param_name, 'REG_BINARY', @value_binary */ EXECUTE @retcode = master.dbo.xp_regread 'HKEY_LOCAL_MACHINE', @oldregkey, @param_name, @param = @value_binary OUTPUT, @no_output = 'no_output' if @retcode <> 0 or @@ERROR <> 0 begin set @retcode = 0 goto FAILURE end EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE', @newregkey, @param_name, 'REG_BINARY', @value_binary if @retcode <> 0 OR @@ERROR <> 0 begin set @retcode = 1 goto FAILURE end end set @retcode = 0 FAILURE: drop table #binaryvalues return @retcode go raiserror('Creating procedure sp_vupgrade_registry', 0,1) GO create procedure sp_vupgrade_registry as set nocount on declare @oldregkey nvarchar(1000) declare @newregkey nvarchar(1000) declare @subscription_name nvarchar(1000) declare @resolver_name nvarchar(1000) declare @resolver_clsid nvarchar(1000) declare @retcode int declare @keyexist int -- raiserror('sp_vupgrade_registry', 0,1) create table #keyexist (keyexist int) set @oldregkey = 'SOFTWARE\Microsoft\MSSQLServer\Replication\Subscriptions\' insert into #keyexist EXECUTE master.dbo.xp_regread 'HKEY_LOCAL_MACHINE', @oldregkey select @keyexist = keyexist from #keyexist if @keyexist = 1 begin -- Move the registered subscriptions to new location in registry create table #syncmgr_subscriptions (subscription_name nvarchar(1000) collate database_default) set @oldregkey = 'SOFTWARE\Microsoft\MSSQLServer\Replication\Subscriptions\' insert into #syncmgr_subscriptions EXECUTE master.dbo.xp_regenumkeys 'HKEY_LOCAL_MACHINE', @oldregkey declare #subscriptioncursor CURSOR LOCAL FAST_FORWARD FOR select DISTINCT subscription_name FROM #syncmgr_subscriptions FOR READ ONLY open #subscriptioncursor fetch next from #subscriptioncursor into @subscription_name while (@@fetch_status <> -1) begin set @newregkey = 'SOFTWARE\Microsoft\Microsoft SQL Server\80\Replication\Subscriptions\' + @subscription_name set @oldregkey = 'SOFTWARE\Microsoft\MSSQLServer\Replication\Subscriptions\' + @subscription_name delete from #keyexist insert into #keyexist EXECUTE master.dbo.xp_regread 'HKEY_LOCAL_MACHINE', @oldregkey select @keyexist = keyexist from #keyexist if @keyexist = 1 begin exec @retcode = sp_MScopyregvalue @oldregkey, @newregkey, 'REG_SZ', 'ProfileName' if @retcode <> 0 begin set @retcode = 1 goto FAILURE end exec @retcode = sp_MScopyregvalue @oldregkey, @newregkey, 'REG_SZ', 'HostName' if @retcode <> 0 begin set @retcode = 1 goto FAILURE end exec @retcode = sp_MScopyregvalue @oldregkey, @newregkey, 'REG_DWORD', 'ReplicationType' if @retcode <> 0 begin set @retcode = 1 goto FAILURE end exec @retcode = sp_MScopyregvalue @oldregkey, @newregkey, 'REG_DWORD', 'SubscriptionType' if @retcode <> 0 begin set @retcode = 1 goto FAILURE end exec @retcode = sp_MScopyregvalue @oldregkey, @newregkey, 'REG_DWORD', 'ExchangeType' if @retcode <> 0 begin set @retcode = 1 goto FAILURE end exec @retcode = sp_MScopyregvalue @oldregkey, @newregkey, 'REG_DWORD', 'Validate' if @retcode <> 0 begin set @retcode = 1 goto FAILURE end exec @retcode = sp_MScopyregvalue @oldregkey, @newregkey, 'REG_DWORD', 'LoginTimeout' if @retcode <> 0 begin set @retcode = 1 goto FAILURE end exec @retcode = sp_MScopyregvalue @oldregkey, @newregkey, 'REG_DWORD', 'QueryTimeout' if @retcode <> 0 begin set @retcode = 1 goto FAILURE end exec @retcode = sp_MScopyregvalue @oldregkey, @newregkey, 'REG_SZ', 'SubscriptionName' if @retcode <> 0 begin set @retcode = 1 goto FAILURE end exec @retcode = sp_MScopyregvalue @oldregkey, @newregkey, 'REG_BINARY', 'LastUpdateTime' if @retcode <> 0 begin set @retcode = 1 goto FAILURE end exec @retcode = sp_MScopyregvalue @oldregkey, @newregkey, 'REG_SZ', 'Subid' if @retcode <> 0 begin set @retcode = 1 goto FAILURE end exec @retcode = sp_MScopyregvalue @oldregkey, @newregkey, 'REG_SZ', 'Publication' if @retcode <> 0 begin set @retcode = 1 goto FAILURE end exec @retcode = sp_MScopyregvalue @oldregkey, @newregkey, 'REG_SZ', 'Publisher' if @retcode <> 0 begin set @retcode = 1 goto FAILURE end exec @retcode = sp_MScopyregvalue @oldregkey, @newregkey, 'REG_SZ', 'PublisherDb' if @retcode <> 0 begin set @retcode = 1 goto FAILURE end exec @retcode = sp_MScopyregvalue @oldregkey, @newregkey, 'REG_DWORD', 'PublisherSecurityMode' if @retcode <> 0 begin set @retcode = 1 goto FAILURE end exec @retcode = sp_MScopyregvalue @oldregkey, @newregkey, 'REG_SZ', 'PublisherLogin' if @retcode <> 0 begin set @retcode = 1 goto FAILURE end exec @retcode = sp_MScopyregvalue @oldregkey, @newregkey, 'REG_SZ', 'PublisherEncryptedPassword' if @retcode <> 0 begin set @retcode = 1 goto FAILURE end exec @retcode = sp_MScopyregvalue @oldregkey, @newregkey, 'REG_BINARY', 'PublisherEncryptedPasswordBinary' if @retcode <> 0 begin set @retcode = 1 goto FAILURE end exec @retcode = sp_MScopyregvalue @oldregkey, @newregkey, 'REG_SZ', 'PublisherAddress' if @retcode <> 0 begin set @retcode = 1 goto FAILURE end exec @retcode = sp_MScopyregvalue @oldregkey, @newregkey, 'REG_SZ', 'PublisherNetwork' if @retcode <> 0 begin set @retcode = 1 goto FAILURE end exec @retcode = sp_MScopyregvalue @oldregkey, @newregkey, 'REG_SZ', 'Subscriber' if @retcode <> 0 begin set @retcode = 1 goto FAILURE end exec @retcode = sp_MScopyregvalue @oldregkey, @newregkey, 'REG_SZ', 'SubscriberDb' if @retcode <> 0 begin set @retcode = 1 goto FAILURE end exec @retcode = sp_MScopyregvalue @oldregkey, @newregkey, 'REG_DWORD', 'SubscriberSecurityMode' if @retcode <> 0 begin set @retcode = 1 goto FAILURE end exec @retcode = sp_MScopyregvalue @oldregkey, @newregkey, 'REG_SZ', 'SubscriberLogin' if @retcode <> 0 begin set @retcode = 1 goto FAILURE end exec @retcode = sp_MScopyregvalue @oldregkey, @newregkey, 'REG_SZ', 'SubscriberEncryptedPassword' if @retcode <> 0 begin set @retcode = 1 goto FAILURE end exec @retcode = sp_MScopyregvalue @oldregkey, @newregkey, 'REG_BINARY', 'SubscriberEncryptedPasswordBinary' if @retcode <> 0 begin set @retcode = 1 goto FAILURE end exec @retcode = sp_MScopyregvalue @oldregkey, @newregkey, 'REG_DWORD', 'SubscriberDatasourceType' if @retcode <> 0 begin set @retcode = 1 goto FAILURE end exec @retcode = sp_MScopyregvalue @oldregkey, @newregkey, 'REG_SZ', 'SubscriberDatabasePath' if @retcode <> 0 begin set @retcode = 1 goto FAILURE end exec @retcode = sp_MScopyregvalue @oldregkey, @newregkey, 'REG_SZ', 'Distributor' if @retcode <> 0 begin set @retcode = 1 goto FAILURE end exec @retcode = sp_MScopyregvalue @oldregkey, @newregkey, 'REG_DWORD', 'DistributorSecurityMode' if @retcode <> 0 begin set @retcode = 1 goto FAILURE end exec @retcode = sp_MScopyregvalue @oldregkey, @newregkey, 'REG_SZ', 'DistributorLogin' if @retcode <> 0 begin set @retcode = 1 goto FAILURE end exec @retcode = sp_MScopyregvalue @oldregkey, @newregkey, 'REG_SZ', 'DistributorEncryptedPassword' if @retcode <> 0 begin set @retcode = 1 goto FAILURE end exec @retcode = sp_MScopyregvalue @oldregkey, @newregkey, 'REG_BINARY', 'DistributorEncryptedPasswordBinary' if @retcode <> 0 begin set @retcode = 1 goto FAILURE end exec @retcode = sp_MScopyregvalue @oldregkey, @newregkey, 'REG_SZ', 'DistributorAddress' if @retcode <> 0 begin set @retcode = 1 goto FAILURE end exec @retcode = sp_MScopyregvalue @oldregkey, @newregkey, 'REG_SZ', 'DistributorNetwork' if @retcode <> 0 begin set @retcode = 1 goto FAILURE end exec @retcode = sp_MScopyregvalue @oldregkey, @newregkey, 'REG_DWORD', 'UseInteractiveResolver' if @retcode <> 0 begin set @retcode = 1 goto FAILURE end -- regdelete returns 'Access Denied' message if key does not exist; check before delete delete from #keyexist insert into #keyexist EXECUTE master.dbo.xp_regread 'HKEY_LOCAL_MACHINE', @oldregkey select @keyexist = keyexist from #keyexist if @keyexist = 1 begin exec @retcode = master.dbo.xp_regdeletekey 'HKEY_LOCAL_MACHINE', @oldregkey if @@error <> 0 OR @retcode <> 0 begin set @retcode = 1 goto FAILURE end end end fetch next from #subscriptioncursor into @subscription_name end close #subscriptioncursor deallocate #subscriptioncursor drop table #syncmgr_subscriptions -- done moving reg keys/values. delete old key; check key exists before delete set @oldregkey = 'SOFTWARE\Microsoft\MSSQLServer\Replication\Subscriptions\' delete from #keyexist insert into #keyexist EXECUTE master.dbo.xp_regread 'HKEY_LOCAL_MACHINE', @oldregkey select @keyexist = keyexist from #keyexist if @keyexist = 1 begin exec @retcode = master.dbo.xp_regdeletekey 'HKEY_LOCAL_MACHINE', @oldregkey if @@error <> 0 OR @retcode <> 0 begin set @retcode = 1 goto FAILURE end end end -- Move the registered article resolvers to new location in registry set @oldregkey = 'SOFTWARE\Microsoft\MSSQLServer\Replication\ArticleResolver' set @newregkey = 'SOFTWARE\Microsoft\Microsoft SQL Server\80\Replication\ArticleResolver' delete from #keyexist insert into #keyexist EXECUTE master.dbo.xp_regread 'HKEY_LOCAL_MACHINE', @oldregkey select @keyexist = keyexist from #keyexist if @keyexist = 1 begin create table #article_resolvers (resolver_name nvarchar(1000) collate database_default, resolver_clsid nvarchar(1000)) insert into #article_resolvers EXECUTE master.dbo.xp_regenumvalues 'HKEY_LOCAL_MACHINE', @oldregkey declare #resolvercursor CURSOR LOCAL FAST_FORWARD FOR select DISTINCT resolver_name, resolver_clsid FROM #article_resolvers FOR READ ONLY open #resolvercursor fetch next from #resolvercursor into @resolver_name, @resolver_clsid while (@@fetch_status <> -1) begin exec @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE', @newregkey, @resolver_name, 'REG_SZ', @resolver_clsid if @retcode <> 0 OR @@ERROR <> 0 begin set @retcode = 1 goto FAILURE end fetch next from #resolvercursor into @resolver_name, @resolver_clsid end -- done moving reg keys/values. delete old key exec @retcode = master.dbo.xp_regdeletekey 'HKEY_LOCAL_MACHINE', @oldregkey if @@error <> 0 OR @retcode <> 0 begin set @retcode = 1 goto FAILURE end close #resolvercursor deallocate #resolvercursor drop table #article_resolvers end set @retcode = 0 FAILURE: drop table #keyexist return @retcode go exec dbo.sp_MS_marksystemobject sp_vupgrade_registry go raiserror('Creating procedure sp_vupgrade_subscription_tables', 0,1) GO create procedure sp_vupgrade_subscription_tables as begin /* * Process schema and metadata changes common to transactional pub/sub databases. Exception is creation * of MSrepl_identity_range table needed for tran and merge publishing databases and merge subscr db's. * * Setup version upgrade procedure call order: * sp_vupgrade_replication -> sp_vupgrade_subscription_databases -> sp_vupgrade_subscription_tables */ -- raiserror('sp_vupgrade_subscription_tables', 0,1) with nowait set nocount on DECLARE @table_name sysname declare @retcode int -- Identity range management; create in publishing databases if exists (select * from sysobjects where name = 'sysarticles') begin if not exists (select * from sysobjects where name = 'MSpub_identity_range') begin CREATE TABLE dbo.MSpub_identity_range ( objid int not null, range bigint not null, pub_range bigint not null, current_pub_range bigint not null, threshold int not null, last_seed bigint null -- It will be not when uninitialized. ) IF @@ERROR <> 0 BEGIN return(1) END -- mark the index as a system object exec dbo.sp_MS_marksystemobject 'MSpub_identity_range' IF @@ERROR <> 0 BEGIN return(1) END create unique nonclustered index unc1MSpub_identity_range on MSpub_identity_range (objid) IF @@ERROR <> 0 BEGIN return(1) END end end -- Identity range management; create in all publishing databases and merge subscription databases (Shiloh) if exists (select * from sysobjects where name = 'sysmergearticles') begin if not exists (select * from sysobjects where name = 'MSrepl_identity_range') begin create table dbo.MSrepl_identity_range ( objid int not NULL primary key, next_seed bigint NULL, --resource control pub_range bigint NULL, --publisher range range bigint NULL, -- set by sp_addmergearticle max_identity bigint NULL, --resource control threshold int NULL, --in percentage, set by sp_addmergearticle current_max bigint NULL --max value for current check constraint,set by sp_addmergearticle ) exec dbo.sp_MS_marksystemobject MSrepl_identity_range if @@ERROR <> 0 return(1) grant select on MSrepl_identity_range to public end end -- Create unique index on tables that did not have one previously. The index is not created -- if duplicates rows exist in the table. -- MSreplication_subscriptions (SQL7.0 SP1) SELECT @table_name = N'MSreplication_subscriptions' IF EXISTS ( SELECT * FROM sysobjects WHERE name = 'MSreplication_subscriptions' ) or EXISTS ( SELECT * FROM sysobjects WHERE name = 'MSsubscription_agents' ) BEGIN IF EXISTS ( SELECT publication, publisher_db, publisher, subscription_type FROM MSreplication_subscriptions GROUP BY publication, publisher_db, publisher, subscription_type HAVING COUNT(*) > 1 ) RAISERROR (21203, 10, 1, @table_name) ELSE IF NOT EXISTS ( SELECT * FROM sysindexes WHERE name = 'uc1MSReplication_subscriptions' AND id = OBJECT_ID('MSreplication_subscriptions') ) CREATE UNIQUE CLUSTERED INDEX uc1MSReplication_subscriptions ON MSreplication_subscriptions(publication, publisher_db, publisher, subscription_type) -- Create MSsubscription_agents table exec @retcode = dbo.sp_MScreate_sub_tables @tran_sub_table = 1, @property_table = 0, @sqlqueue_table = 0 IF @@ERROR <> 0 or @retcode <> 0 RETURN(1) -- Add new columns to MSsubscription_agents, for 8.0 pre beta upgrade. -- status of the last sync (Shiloh) if not exists (select * from syscolumns where id = object_id('MSsubscription_agents') and name = 'last_sync_status') begin alter table MSsubscription_agents add last_sync_status int NULL if @@ERROR <> 0 return 1 end -- summary message of the last sync (Shiloh) if not exists (select * from syscolumns where id = object_id('MSsubscription_agents') and name = 'last_sync_summary') begin alter table MSsubscription_agents add last_sync_summary sysname NULL if @@ERROR <> 0 return 1 end -- summary message of the last sync (Shiloh) if not exists (select * from syscolumns where id = object_id('MSsubscription_agents') and name = 'last_sync_time') begin alter table MSsubscription_agents add last_sync_time datetime NULL if @@ERROR <> 0 return 1 end END -- MSreplication_objects (SQL7.0 SP1) SELECT @table_name = N'MSreplication_objects' IF EXISTS ( SELECT * FROM sysobjects WHERE name = 'MSreplication_objects' ) BEGIN IF EXISTS ( SELECT object_name FROM MSreplication_objects GROUP BY object_name HAVING COUNT(*) > 1 ) RAISERROR (21203, 10, 3, @table_name) ELSE IF NOT EXISTS ( SELECT * FROM sysindexes WHERE name = 'ucMSreplication_objects' AND id = OBJECT_ID('MSreplication_objects') ) CREATE UNIQUE CLUSTERED INDEX ucMSreplication_objects ON dbo.MSreplication_objects(object_name) END -- MSreplication_queue (SQL2000 SP3) SELECT @table_name = N'MSreplication_queue' IF EXISTS ( SELECT * FROM sysobjects WHERE name = @table_name ) BEGIN exec @retcode = sp_MScreate_sub_tables @tran_sub_table = 0, @property_table = 0, @sqlqueue_table = 1 IF @@ERROR <> 0 or @retcode <> 0 RETURN(1) END -- MSrepl_queuedtraninfo (SQL2000 SP3) SELECT @table_name = N'MSrepl_queuedtraninfo' IF EXISTS ( SELECT * FROM sysobjects WHERE name = @table_name ) BEGIN exec @retcode = sp_MScreate_sub_tables @tran_sub_table = 0, @property_table = 0, @sqlqueue_table = 1 IF @@ERROR <> 0 or @retcode <> 0 RETURN(1) END end go exec dbo.sp_MS_marksystemobject sp_vupgrade_subscription_tables go raiserror('Creating procedure sp_vupgrade_mergetables', 0,1) GO create procedure sp_vupgrade_mergetables( @skip_procgen bit = 0 ) as begin /* * Process schema and metadata changes common to transactional pub/sub databases. * * @skip_procgen is set by sp_restoredbreplication when calling this proc directly to update * system tables during restore of a down-level (e.g. - SQL7.0) database to current version * * Setup version upgrade procedure call order: * sp_vupgrade_replication -> sp_vupgrade_subscription_databases -> sp_vupgrade_mergetables */ set nocount on declare @artnick int declare @objid int declare @col_track int declare @article sysname declare @pubname sysname declare @artid uniqueidentifier declare @pubid uniqueidentifier declare @qualified_name nvarchar(257) declare @source_owner sysname declare @source_object sysname declare @table_name sysname declare @retcode integer declare @snapshot_ready int declare @cmd nvarchar(4000) declare @distributor sysname -- raiserror('sp_vupgrade_mergetables', 0,1) /* * sysmergearticles */ if (exists (select * from sysobjects where name = 'sysmergearticles')) begin -- Set all invalid sysmergearticles.sync_objid to the corresponding -- objid, this will allow regeneration of article procs to succeed update dbo.sysmergearticles set sync_objid = objid where object_name(sync_objid) is null if @@ERROR<>0 return(1) exec @retcode = dbo.sp_MSUpgradeConflictTable @skip_procgen if @@ERROR<>0 or @retcode<>0 return (1) if not exists (select * from syscolumns where id = object_id('sysmergearticles') and name = 'maxversion_at_cleanup') begin alter table sysmergearticles add maxversion_at_cleanup int NOT NULL default 1 if @@ERROR <> 0 return 1 end if not exists (select * from syscolumns where id = object_id('sysmergearticles') and name = 'published_in_tran_pub') begin alter table sysmergearticles add published_in_tran_pub bit NOT NULL default 0 if @@ERROR <> 0 return 1 end if not exists (select * from sysobjects where name = 'sysmergeschemaarticles') begin create table dbo.sysmergeschemaarticles ( name sysname NOT NULL, type tinyint NULL, objid int NOT NULL, artid uniqueidentifier NOT NULL, description nvarchar(255) NULL, pre_creation_command tinyint NULL, pubid uniqueidentifier NOT NULL, status tinyint NULL, creation_script nvarchar(255) NULL, schema_option binary(8) NULL, destination_object sysname NOT NULL, destination_owner sysname NULL -- Note: Please update sysmergeextendedarticlesview whenever -- there is a schema change in sysmergeschemaarticles ) exec dbo.sp_MS_marksystemobject sysmergeschemaarticles create unique clustered index uc1sysmergeschemaarticles on sysmergeschemaarticles(artid, pubid) end if not exists (select * from sysobjects where name = 'MSmerge_errorlineage') begin create table dbo.MSmerge_errorlineage ( tablenick int NOT NULL, rowguid uniqueidentifier NOT NULL, lineage varbinary(255) ) exec dbo.sp_MS_marksystemobject MSmerge_errorlineage create unique clustered index uc1errorlineage on MSmerge_errorlineage(tablenick, rowguid) grant select on MSmerge_errorlineage to public end if not exists (select * from sysobjects where name = 'MSmerge_altsyncpartners') begin create table dbo.MSmerge_altsyncpartners ( subid uniqueidentifier not null, alternate_subid uniqueidentifier not null, description nvarchar(255) NULL ) exec dbo.sp_MS_marksystemobject MSmerge_altsyncpartners create unique clustered index uciMSmerge_altsyncpartners on dbo.MSmerge_altsyncpartners(subid, alternate_subid) end -- create view now that sysmergearticles is altered and sysmergeextendedarticles is created if exists (select * from sysobjects where name='sysmergeextendedarticlesview') begin drop view dbo.sysmergeextendedarticlesview end -- cannot create view directly in proc exec ('create view dbo.sysmergeextendedarticlesview as select name, type, objid, sync_objid, view_type, artid, description, pre_creation_command, pubid, nickname, column_tracking, status, conflict_table, creation_script, conflict_script, article_resolver, ins_conflict_proc, insert_proc, update_proc, select_proc, schema_option, destination_object, resolver_clsid, subset_filterclause, missing_col_count, missing_cols, columns, resolver_info, view_sel_proc, gen_cur, excluded_cols, excluded_col_count, vertical_partition, identity_support, destination_owner, before_image_objid, before_view_objid, verify_resolver_signature, allow_interactive_resolver, fast_multicol_updateproc, check_permissions, maxversion_at_cleanup, published_in_tran_pub from sysmergearticles union all select name, type, objid, NULL, NULL, artid, description, pre_creation_command, pubid, NULL, NULL, status, NULL, creation_script, NULL, NULL, NULL, NULL, NULL, NULL, schema_option, destination_object, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, destination_owner, NULL, NULL, NULL, 0, 0, 0, NULL, 0 from sysmergeschemaarticles go') exec dbo.sp_MS_marksystemobject sysmergeextendedarticlesview -- Do not regenerate views, procs if this is called from sp_restoredbreplication. Restore only -- needs to update schema, then it can call existing system procs to remove db replication cleanly if @skip_procgen = 0 begin select @artnick = min(a.nickname) from sysmergearticles a inner join sysmergepublications p on p.pubid = a.pubid where p.snapshot_ready =1 while @artnick is not null begin -- find base table to compute number of columns select @objid = objid, @col_track = column_tracking from sysmergearticles where nickname = @artnick -- regenerate the triggers select @source_owner = user_name(uid), @source_object = name from sysobjects where id = @objid select @qualified_name = QUOTENAME(@source_owner) + '.' + QUOTENAME(@source_object) exec dbo.sp_MSaddmergetriggers @qualified_name, NULL, @col_track /* Loop through all articles that this table is involved in and regenerate the article procs */ declare hcArtCursor CURSOR LOCAL FAST_FORWARD FOR select artid, pubid from sysmergearticles where nickname = @artnick order by artid, pubid OPEN hcArtCursor FETCH hcArtCursor INTO @artid, @pubid WHILE (@@fetch_status <> -1) BEGIN select @pubname = name, @snapshot_ready = snapshot_ready from sysmergepublications where pubid = @pubid -- regenerate procs, triggers, and views only for articles with snapshot ready if @snapshot_ready>0 begin declare @rgcol nvarchar(270) declare @indname nvarchar(270) declare @quotedname nvarchar(270) declare @conflict_table sysname declare @conflict_table_id int declare @owner sysname select @article = name, @conflict_table=conflict_table, @conflict_table_id=object_id(conflict_table) from sysmergearticles where artid = @artid and pubid = @pubid --make sure conflict table has already got the indexes needed for performance enhancement --if not there we will add it up if ( @conflict_table_id is not null) and not exists (select * from sysindexes where id = @conflict_table_id and keys is not null) begin select @owner=user_name(uid) from sysobjects where id= @conflict_table_id select @rgcol = QUOTENAME(name) from syscolumns where id = @objid and ColumnProperty(id, name, 'isrowguidcol') = 1 select @indname = 'uc_' + @conflict_table if len(@indname) > 128 begin select @indname = substring(@indname,1,92) + convert(nvarchar(36), newid()) end set @indname = QUOTENAME(@indname) set @quotedname = QUOTENAME(@owner) + '.' + QUOTENAME(@conflict_table) exec ('Create unique clustered index ' + @indname + ' on ' + @quotedname + ' (' + @rgcol + ', origin_datasource)' ) if @@error <> 0 return (1) end -- remake the articles procs exec @retcode = dbo.sp_MSsetartprocs @publication = @pubname, @article = @article, @force_flag = 1 if @@ERROR <>0 OR @retcode <>0 return (1) END FETCH hcArtCursor INTO @artid, @pubid END CLOSE hcArtCursor DEALLOCATE hcArtCursor -- we no longer try to delete metadata rows that might have truncated colv1 -- deleting can cause non-convergence problems where they previously didn't -- exist, so we will try to patch up any truncated colv1 values in the merge agent. -- find next article select @artnick = min(a.nickname) from sysmergearticles a inner join sysmergepublications p on p.pubid = a.pubid where p.snapshot_ready > 0 and a.nickname > @artnick end -- end colv metadata fixup, article proc and trigger re-gen -- Loop over publications and recreate the views, skipping publications where snapshot is not ready select @pubname = min(name) from sysmergepublications where UPPER(publisher)=UPPER(@@SERVERNAME) and publisher_db=db_name() and snapshot_ready > 0 while @pubname is not null begin -- remake the publication views exec dbo.sp_MSpublicationview @pubname, 1 select @pubname = min(name) from sysmergepublications where name > @pubname and UPPER(publisher)=UPPER(@@SERVERNAME) and publisher_db=db_name() and snapshot_ready > 0 end end -- end @skip_procgen -- check if the distributor is on the same server as the publisher -- if so fix up the PAL user role. SELECT @distributor = datasource FROM master..sysservers WHERE srvstatus & 8 <> 0 IF @@error = 0 and @distributor IS not NULL BEGIN SELECT @distributor = RTRIM(@distributor) -- if the distributor is on the same server. Hence we can fix the pal role -- right now instead of waiting for a snapshot to do it. IF LOWER(@@SERVERNAME) = LOWER(@distributor) BEGIN declare @role sysname declare @pubidother uniqueidentifier -- we need to fix the pal role for all publications in the current database declare pubs_cursor cursor LOCAL FAST_FORWARD for select pubid from dbo.sysmergepublications where UPPER(publisher) collate database_default = UPPER(@@servername) collate database_default and publisher_db = db_name() open pubs_cursor fetch pubs_cursor into @pubidother while (@@fetch_status <> -1) begin exec @retcode = sp_MSrepl_FixPALRole @pubidother, @role output if (@role is NULL or @retcode <> 0 or @@error <> 0) begin return 1 end fetch pubs_cursor into @pubidother end close pubs_cursor deallocate pubs_cursor END else begin -- force invalidate snapshot for all the publications. -- this is needed for sp3 upgrade since we have introduced role based -- security in shiloh sp3. the role will be created and setup when -- the snapshot agent calls sp_MSenumpubreferences raiserror(20605, 10, -1) update dbo.sysmergepublications set snapshot_ready=2 where UPPER(publisher) collate database_default = UPPER(@@servername) collate database_default and publisher_db = db_name() end END else begin -- force invalidate snapshot for all the publications. -- this is needed for sp3 upgrade since we have introduced role based -- security in shiloh sp3. the role will be created and setup when -- the snapshot agent calls sp_MSenumpubreferences update dbo.sysmergepublications set snapshot_ready=2 where UPPER(publisher) collate database_default = UPPER(@@servername) collate database_default and publisher_db = db_name() end -- revoke select access to public on table which were previously granted to public revoke select on MSmerge_errorlineage from public revoke select on MSrepl_identity_range from public revoke select on sysmergearticles from public grant select(nickname,gen_cur,maxversion_at_cleanup) on sysmergearticles to public revoke select on sysmergesubscriptions from public revoke select on MSmerge_replinfo from public revoke select on MSmerge_tombstone from public revoke select on MSmerge_contents from public revoke select on MSmerge_genhistory from public revoke select on MSmerge_delete_conflicts from public revoke select on sysmergeschemachange from public revoke select on sysmergesubsetfilters from public end -- end sysmergearticles modifications SELECT @table_name = N'MSmerge_tombstone' IF EXISTS ( SELECT * FROM sysobjects WHERE name = 'MSmerge_tombstone' ) BEGIN IF EXISTS (SELECT * FROM sysindexes WHERE name = 'unc3MSmerge_tombstone' AND id = OBJECT_ID('MSmerge_tombstone')) drop index MSmerge_tombstone.unc3MSmerge_tombstone END SELECT @table_name = N'MSmerge_contents' IF EXISTS ( SELECT * FROM sysobjects WHERE name = 'MSmerge_contents' ) BEGIN IF EXISTS (SELECT * FROM sysindexes WHERE name = 'nc2MSmerge_contents' AND id = OBJECT_ID('MSmerge_contents')) drop index MSmerge_contents.nc2MSmerge_contents IF EXISTS (SELECT * FROM sysindexes WHERE name = 'nc3MSmerge_contents' AND id = OBJECT_ID('MSmerge_contents')) drop index MSmerge_contents.nc3MSmerge_contents IF EXISTS (SELECT * FROM sysindexes WHERE name = 'nc4MSmerge_contents' AND id = OBJECT_ID('MSmerge_contents')) drop index MSmerge_contents.nc4MSmerge_contents IF EXISTS (SELECT * FROM sysindexes WHERE name = 'unc3SycContents' AND id = OBJECT_ID('MSmerge_contents')) drop index MSmerge_contents.unc3SycContents create index nc2MSmerge_contents on MSmerge_contents(generation) if @@ERROR <> 0 return 1 create index nc3MSmerge_contents on MSmerge_contents(partchangegen) if @@ERROR <> 0 return 1 create index nc4MSmerge_contents on MSmerge_contents(rowguid) if @@ERROR <> 0 return 1 END if (exists (select * from sysobjects where name = 'sysmergearticles')) begin -- before image tables declare @binames table (biname sysname) insert into @binames select name from sysobjects where xtype='U' and name like 'MS_bi%' and id in (select before_image_objid from sysmergearticles) declare @biname nvarchar(255) set @biname= (select top 1 biname from @binames) while @biname is not null begin set @cmd= 'drop index ' + quotename(@biname) + '.' + quotename(@biname + '_gen') exec dbo.sp_executesql @cmd set @cmd= 'create clustered index ' + quotename(@biname + '_gen') + ' on ' + quotename(@biname) + '(generation)' exec dbo.sp_executesql @cmd delete from @binames where biname=@biname set @biname= (select top 1 biname from @binames) end end -- remove orphaned rows in MSmerge_contents if ( exists (select * from sysobjects where name = 'sysmergearticles') and exists (select * from sysobjects where name = 'sysmergepublications') and exists (select * from sysobjects where name = 'MSmerge_genhistory') and exists (select * from sysobjects where name = 'MSmerge_contents') and exists (select * from sysobjects where name = 'MSmerge_tombstone') ) begin exec @retcode= sp_MSpurgecontentsorphans if @retcode<>0 or @@error<>0 return 1 end end GO exec sp_MS_marksystemobject 'sp_vupgrade_mergetables' go raiserror('Creating procedure sp_vupgrade_subpass', 0,1) GO create procedure sp_vupgrade_subpass as begin /* * Upgrade replication ftp_password and distributor_passwords * in subscriber database. * * Setup version upgrade procedure call order: * sp_vupgrade_replication -> sp_vupgrade_subscription_databases -> sp_vupgrade_subpass */ begin transaction /* * MSsubscription_properties */ if exists (select name from sysobjects where name='MSsubscription_properties') begin if not exists (select * from syscolumns where id = Object_Id('MSsubscription_properties') and name = 'ftp_password' and length = '1048') begin declare @dbname sysname declare @cmptlevel tinyint set @dbname = db_name() select @cmptlevel = cmptlevel from master..sysdatabases where name = @dbname collate database_default if @cmptlevel < 70 begin raiserror (15048, -1, -1, 70, 70, 70, 80) end else begin /* * alter ftp_password column from sysname to nvarchar(524) */ exec( 'alter table MSsubscription_properties alter column ftp_password nvarchar(524)' ) exec( 'alter table MSsubscription_properties alter column distributor_password nvarchar(524)' ) exec( 'alter table MSsubscription_properties alter column publisher_password nvarchar(524)' ) exec( 'alter table MSsubscription_properties alter column dts_package_password nvarchar(524)' ) end /* * convert all the ftp_passwords to new encryption */ declare @ftp_password nvarchar(524) declare @distributor_password nvarchar(524) declare @publisher_password nvarchar(524) declare @dts_package_password nvarchar(524) declare @retcode int declare cur_MSsubscription_properties CURSOR LOCAL FORWARD_ONLY for select ftp_password, distributor_password, publisher_password, dts_package_password from MSsubscription_properties for update of ftp_password, distributor_password, publisher_password, dts_package_password open cur_MSsubscription_properties fetch next from cur_MSsubscription_properties into @ftp_password, @distributor_password, @publisher_password, @dts_package_password while ( @@fetch_status <> -1 ) begin EXEC @retcode = master.dbo.xp_repl_convert_encrypt @ftp_password OUTPUT IF @@error <> 0 OR @retcode <> 0 begin rollback transaction return 1 end EXEC @retcode = master.dbo.xp_repl_convert_encrypt @distributor_password OUTPUT IF @@error <> 0 OR @retcode <> 0 begin rollback transaction return 1 end EXEC @retcode = master.dbo.xp_repl_convert_encrypt @publisher_password OUTPUT IF @@error <> 0 OR @retcode <> 0 begin rollback transaction return 1 end EXEC @retcode = master.dbo.xp_repl_convert_encrypt @dts_package_password OUTPUT IF @@error <> 0 OR @retcode <> 0 begin rollback transaction return 1 end update MSsubscription_properties set ftp_password=@ftp_password, distributor_password=@distributor_password, publisher_password=@publisher_password, dts_package_password=@dts_package_password where current of cur_MSsubscription_properties fetch next from cur_MSsubscription_properties into @ftp_password, @distributor_password, @publisher_password, @dts_package_password end end end commit transaction end GO exec sp_MS_marksystemobject 'sp_vupgrade_subpass' go raiserror('Creating procedure sp_vupgrade_MSsubscription_properties', 0,1) GO create procedure sp_vupgrade_MSsubscription_properties as begin /* * Process schema and metadata changes common to transactional and merge MSsubscription_properties. * * Setup version upgrade procedure call order: * sp_vupgrade_replication -> sp_vupgrade_subscription_databases -> sp_vupgrade_MSsubscription_properties */ set nocount on declare @cmd nvarchar(1000) declare @table_name sysname -- raiserror('sp_vupgrade_MSsubscription_properties', 0,1) if exists( select * from sysobjects where name = 'MSsubscription_properties' and type = 'U') begin -- Add FTP properties to MSsubscription_properties. if not exists (select * from syscolumns where name = 'ftp_address' and id = OBJECT_ID('MSsubscription_properties')) begin alter table MSsubscription_properties ADD ftp_address sysname NULL if @@ERROR <> 0 return 1 end if not exists (select * from syscolumns where name = 'ftp_port' and id = OBJECT_ID('MSsubscription_properties')) begin alter table MSsubscription_properties ADD ftp_port int NULL if @@ERROR <> 0 return 1 end if not exists (select * from syscolumns where name = 'ftp_login' and id = OBJECT_ID('MSsubscription_properties')) begin alter table MSsubscription_properties ADD ftp_login sysname NULL if @@ERROR <> 0 return 1 end if not exists (select * from syscolumns where name = 'ftp_password' and id = OBJECT_ID('MSsubscription_properties')) begin alter table MSsubscription_properties ADD ftp_password sysname NULL if @@ERROR <> 0 return 1 end -- Portable snapshot (Shiloh) if not exists (select * from syscolumns where name = 'alt_snapshot_folder' and id = OBJECT_ID('MSsubscription_properties')) begin alter table MSsubscription_properties ADD alt_snapshot_folder nvarchar(255) NULL if @@ERROR <> 0 return 1 end if not exists (select * from syscolumns where name = 'working_directory' and id = OBJECT_ID('MSsubscription_properties')) begin alter table MSsubscription_properties ADD working_directory nvarchar(255) NULL if @@ERROR <> 0 return 1 end -- Subscriber need only set this bit and have valid login info to publisher (Shiloh) if not exists (select * from syscolumns where name = 'use_ftp' and id = OBJECT_ID('MSsubscription_properties')) begin alter table MSsubscription_properties ADD use_ftp bit default 0 NOT NULL if @@ERROR <> 0 return 1 end -- Since ftp login information is not required to be persisted at the -- database anymore and the use_ftp column is now the sole indicator -- of whether ftp is going to be used for a particular subscription, -- set the use_ftp column to 1 for subscriptions that used to have -- a non-null ftp address if exists (select * from syscolumns where id = object_id('MSsubscription_properties') and name = 'ftp_address') begin -- must exec in separate process; deferred syntax will fail if update references non-existent column select @cmd = 'update dbo.MSsubscription_properties set use_ftp = 1 where ftp_address is not null and ftp_address <> N''''' exec (@cmd) end -- Transformable subscriptions (Shiloh) if not exists (select * from syscolumns where name = 'dts_package_name' and id = OBJECT_ID('MSsubscription_properties')) begin alter table MSsubscription_properties ADD dts_package_name sysname NULL if @@ERROR <> 0 return 1 end if not exists (select * from syscolumns where name = 'dts_package_password' and id = OBJECT_ID('MSsubscription_properties')) begin alter table MSsubscription_properties ADD dts_package_password nvarchar(524) NULL if @@ERROR <> 0 return 1 end if not exists (select * from syscolumns where name = 'dts_package_location' and id = OBJECT_ID('MSsubscription_properties')) begin alter table MSsubscription_properties ADD dts_package_location int default 1 NOT NULL if @@ERROR <> 0 return 1 end -- Windows Synchronization Manager support (Shiloh) if not exists (select * from syscolumns where name = 'enabled_for_syncmgr' and id = OBJECT_ID('MSsubscription_properties')) begin alter table MSsubscription_properties ADD enabled_for_syncmgr bit default 0 NOT NULL if @@ERROR <> 0 return 1 end -- Remote (DCOM) agents support (Shiloh) if not exists (select * from syscolumns where id = object_id('MSsubscription_properties') and name = 'offload_agent') begin alter table MSsubscription_properties ADD offload_agent bit default 0 NOT NULL if @@ERROR <> 0 return 1 end if not exists (select * from syscolumns where id = object_id('MSsubscription_properties') and name = 'offload_server') begin alter table MSsubscription_properties ADD offload_server sysname default NULL if @@ERROR <> 0 return 1 end -- Dynamic snapshot location (Shiloh) if not exists (select * from syscolumns where id = object_id('MSsubscription_properties') and name = 'dynamic_snapshot_location') begin alter table MSsubscription_properties ADD dynamic_snapshot_location sysname default NULL if @@ERROR <> 0 return 1 end -- MSsubscription_properties indexes (SQL7.0 SP1) select @table_name = N'MSsubscription_properties' if exists( select * from sysobjects where name = 'MSsubscription_properties' ) begin if exists( select publication, publisher_db, publisher from MSsubscription_properties group by publication, publisher_db, publisher having count(*) > 1 ) raiserror(21203, 10, 2, @table_name) else if not exists( select * from sysindexes where name = 'uc1MSsubscription_properties' and id = OBJECT_ID('MSsubscription_properties') ) create unique clustered index uc1MSsubscription_properties on MSsubscription_properties(publication, publisher_db, publisher) end end end go exec sp_MS_marksystemobject 'sp_vupgrade_MSsubscription_properties' go raiserror('Creating procedure sp_vupgrade_replication', 0,1) GO create procedure sp_vupgrade_replication ( @login sysname = N'sa', @password sysname = N'', @ver_old int = 517, @force_remove tinyint = 0, @security_mode bit = 0 ) as begin /* * Dispatcher proc for handling schema and metadata changes during setup initiated version upgrade * for replication components. Any schema changes to replication system tables may require modifications * here to maintain upgrade path. All modifications called in these procs are within "if exists" checks * making them repeatable for debugging and to support incremental upgrades (e.g. Beta 1 to Beta 2 to RTM) * * If server is a distributor, run new instdist.sql against all distribution dbs. * * This proc gets called by setup at the end of an install over an existing version. */ set nocount on declare @dbname sysname declare @has_dbaccess bit declare @install_path nvarchar(255) declare @osql_path nvarchar(260) declare @osql_cmd nvarchar(512) declare @osql_for_nt int declare @retcode int declare @platform_nt binary declare @db_distbit int declare @ver_min int declare @ver_retention int select @db_distbit = 16 select @platform_nt = 0x1 select @ver_retention = 576 --build # on 9/17 -- raiserror('sp_vupgrade_replication', 0,1) with nowait /* * obsolete check; ver check was to prevent repl upgrade from * versions prior to SQL7.0 Beta 3; check is removed by setting @ver_min = -1 */ select @ver_min= -1 -- change if later wish to support a minimum upgrade version if ( @ver_old < @ver_min ) or ( @force_remove = 1 ) exec dbo.sp_removesrvreplication else begin /* * always need to run instdist.sql to update distribution databases on a distributor * setup must restart in non-single user mode so we can shell out to run instdist.sql scripts */ if exists( select * from master..sysdatabases where category & @db_distbit = @db_distbit ) begin /* ** Get installation path -- osql client (TOOLS) path */ EXECUTE @retcode = master.dbo.sp_MSgettools_path @osql_path OUTPUT IF ( @@ERROR <> 0 ) OR ( @retcode <> 0 ) or ( @osql_path is NULL ) or ( @osql_path = '' ) BEGIN RETURN (1) END /* ** Get installation path -- instance specific (INSTALL) directory */ exec @retcode = master.dbo.sp_MSget_setup_paths @sql_path = @install_path output IF @@ERROR<> 0 OR @retcode <> 0 or @install_path is NULL or @install_path=N'' BEGIN RETURN (1) END -- Set the flag for platform if (( platform() & @platform_nt = @platform_nt )) select @osql_for_nt = 1 else select @osql_for_nt = 0 declare cur_distdb CURSOR LOCAL FAST_FORWARD for select name, has_dbaccess(name) from master..sysdatabases where category & @db_distbit = @db_distbit for read only open cur_distdb fetch cur_distdb into @dbname, @has_dbaccess while ( @@fetch_status <> -1 ) begin -- if distribution database is available upgrade it; if offline error out if ( @has_dbaccess = 1 ) begin raiserror( 21374, 0, 1, @dbname) with nowait /* * Format osql cmd line appropriate for security mode and OS to run instdist.sql against * each distribution database. Instdist.sql will recompile procs and will also do some * schema and metadata upgrade of changed replication tables. Query timeout increased to * make enough time for alter tables in instdist.sql run for upgrade to complete. */ if ( @osql_for_nt = 1 ) select @osql_cmd = N'" "' else select @osql_cmd = N' "' -- Cannot specify -S w/ -E for local execution, SID does not map (nofix) if ( @security_mode = 1 and @osql_for_nt = 1 ) begin select @osql_cmd = @osql_cmd + fn_escapecmdshellsymbolsremovequotes(@osql_path) collate database_default + '\binn\osql" -E ' if serverproperty('instancename') is not null select @osql_cmd = @osql_cmd + ' -S"' + fn_escapecmdshellsymbols(@@SERVERNAME) collate database_default + '" ' end else select @osql_cmd = @osql_cmd + fn_escapecmdshellsymbolsremovequotes(@osql_path) collate database_default + '\binn\osql" -U' + fn_escapecmdshellsymbols(isnull(@login, N'sa')) collate database_default + ' -P' + fn_escapecmdshellsymbols(isnull(@password, N'')) collate database_default + ' -S"' + fn_escapecmdshellsymbols(@@SERVERNAME) collate database_default + '" ' select @osql_cmd = @osql_cmd + ' -l30 -t120 ' select @osql_cmd = @osql_cmd + ' -b ' + ' -d' + fn_escapecmdshellsymbols(@dbname) collate database_default select @osql_cmd = @osql_cmd + ' -i' + '"' + fn_escapecmdshellsymbolsremovequotes(@install_path) collate database_default + '\install\instdist.sql"' + ' -o' + '"' + fn_escapecmdshellsymbolsremovequotes(@install_path) collate database_default + '\install\instdist.out"' if (@osql_for_nt = 1) select @osql_cmd = @osql_cmd + ' "' exec @retcode = master..xp_cmdshell @osql_cmd if @retcode <> 0 or @@error <> 0 begin raiserror (14113, 16, -1, @osql_cmd, 'instdist.out') end /* * Process schema and metadata changes for each distribution database */ select @dbname = quotename(@dbname) exec ('use '+ @dbname + ' exec dbo.sp_vupgrade_distdb') if @@error <> 0 return(1) end else begin /* Report informational message stating distribution ** database is not accessible. */ raiserror( 21378, 10, 1, @dbname) with nowait end fetch next from cur_distdb into @dbname, @has_dbaccess end close cur_distdb deallocate cur_distdb end -- vupgrade_publisher runs at exec @retcode = dbo.sp_vupgrade_publisher @ver_old = @ver_old, @ver_retention = @ver_retention if @retcode<>0 or @@error<>0 return (1) -- Update subscription database schema exec @retcode = dbo.sp_vupgrade_subscription_databases if @retcode <> 0 or @@error <> 0 return (1) end return (0) end go exec dbo.sp_MS_marksystemobject sp_vupgrade_replication go raiserror('Creating procedure sp_vupgrade_distdb', 0,1) go create procedure sp_vupgrade_distdb as begin /* * Process schema and metadata changes specific to a distribution database. Some schema modifications * may have already been made by the apply of instdist.sql against the distribution database. Both steps * are needed for a complete distribution database upgrade. * * Setup version upgrade procedure call order: * sp_vupgrade_replication -> sp_vupgrade_distdb */ set nocount on declare @table_name sysname declare @retcode integer -- raiserror('sp_vupgrade_publisher', 0,1) with nowait /* * MSdistribution_agents */ if exists (select name from sysobjects where name='MSdistribution_agents') begin if not exists (select * from syscolumns where id = object_id('MSdistribution_agents') and name = 'queue_server') begin alter table MSdistribution_agents add queue_server sysname null EXEC dbo.sp_MSupdate_mqserver_distdb end end /* mark helper tables in msdb as system object */ IF EXISTS (SELECT * FROM msdb..sysobjects WHERE name = 'MSdistpublishers' and xtype = 'U') begin exec msdb.dbo.sp_MS_marksystemobject MSdistpublishers end /* Create MSdistributiondbs table */ IF EXISTS (SELECT * FROM msdb..sysobjects WHERE name = 'MSdistributiondbs' and xtype = 'U') begin exec msdb.dbo.sp_MS_marksystemobject MSdistributiondbs end /* create MSdistributor table */ IF EXISTS (SELECT * FROM msdb..sysobjects WHERE name = 'MSdistributor' and xtype = 'U') begin exec msdb.dbo.sp_MS_marksystemobject MSdistributor end /* create sysreplicationalerts table */ IF EXISTS (SELECT * FROM msdb..sysobjects WHERE name = 'sysreplicationalerts' and xtype = 'U') begin exec msdb.dbo.sp_MS_marksystemobject sysreplicationalerts end /* create MSagent_profiles table */ IF EXISTS (SELECT * FROM msdb..sysobjects WHERE name = 'MSagent_profiles' and xtype = 'U') begin exec msdb.dbo.sp_MS_marksystemobject MSagent_profiles end /* create MSagent_parameters table */ IF EXISTS (SELECT * FROM msdb..sysobjects WHERE name = 'MSagent_parameters' and xtype = 'U') begin exec msdb.dbo.sp_MS_marksystemobject MSagent_parameters end /* create MSdatatype_mappings table */ IF EXISTS (SELECT * FROM msdb..sysobjects WHERE name = 'MSdatatype_mappings' and xtype = 'U') begin exec msdb.dbo.sp_MS_marksystemobject MSdatatype_mappings end end go exec dbo.sp_MS_marksystemobject sp_vupgrade_distdb go raiserror('Creating procedure sp_vupgrade_publisher', 0,1) go create procedure sp_vupgrade_publisher @ver_old int, @ver_retention int as begin /* * Process schema and metadata changes specific to a publisher and dispatch calls to sp_vupgrade_publisherdb * for any databases marked with the publishing bits. * * Setup version upgrade procedure call order: * sp_vupgrade_replication -> sp_vupgrade_publisher */ set nocount on declare @proc_name nvarchar(350) declare @publication sysname declare @upgraded bit declare @retcode int declare @publisher_db nvarchar(270) declare @agentname sysname declare @has_dbaccess bit -- raiserror('sp_vupgrade_publisher', 0,1) /* * Expired subscription cleanup agent name needs set to localized string (message 20569) and * jobstep set to correct procedure name based on name change between SQL7.0 and SQL7.5 */ set @agentname = formatmessage(20569) update msdb.dbo.sysjobs set name = @agentname from msdb.dbo.sysjobs, msdb.dbo.sysjobsteps as s where msdb.dbo.sysjobs.job_id = s.job_id and ( upper(s.command) = upper(N'EXEC sp_MScleanup_subscription') or upper(s.command) = upper(N'EXEC dbo.sp_MScleanup_subscription') ) update msdb.dbo.sysjobsteps set command = N'EXEC dbo.sp_expired_subscription_cleanup' where upper(command) = upper(N'EXEC sp_MScleanup_subscription') or upper(command) = upper(N'EXEC dbo.sp_MScleanup_subscription') /* * Process schema and metadata changes for each publishing database on the publisher. * * Transactional replication system tables at the publisher are updated by sp_vupgrade_publisherdb. * Most merge system tables exist in both the publishing and subscribing databases; merge schema * and metadata changes are processed by a separate pass over all databases in sp_vupgrade_mergetables. */ declare DC cursor local FAST_FORWARD for select distinct N'[' + replace(name, N']', N']]') + N']', has_dbaccess(name) from master..sysdatabases -- where ((category & 4) = 4) or ((category & 1) = 1) WHERE name <> N'master' collate database_default AND name <> N'tempdb' collate database_default AND name <> N'msdb' collate database_default for read only open DC fetch DC into @publisher_db, @has_dbaccess while (@@fetch_status <> -1) begin -- upgrade repl tables in publishing dbs if needed -- skip any database in an offline state and write warning to upgrade log if ( @has_dbaccess = 1 ) begin raiserror( 21375, 10, 1, @publisher_db) with nowait select @proc_name = @publisher_db + '.dbo.sp_vupgrade_publisherdb' exec @retcode = @proc_name @ver_old = @ver_old, @ver_retention = @ver_retention if @retcode<>0 or @@ERROR<>0 begin close DC deallocate DC return (1) end end else begin -- report informational message stating database is not accessible. raiserror( 21376, 10, 1, @publisher_db) with nowait end fetch DC into @publisher_db, @has_dbaccess end close DC deallocate DC /* * We need to mark sp_MScleanupmergepublisher as a startup procedure * if there are any databases enabled for merge replication. */ if exists (select * from sysdatabases where (category & 4) <> 0) begin exec dbo.sp_procoption 'sp_MScleanupmergepublisher', 'startup', 'true' end end go exec dbo.sp_MS_marksystemobject sp_vupgrade_publisher go raiserror('Creating procedure sp_vupgrade_syscol_status', 0,1) go create procedure sp_vupgrade_syscol_status as begin /* * Transactional published tables should have their column bits set to indicate they are published. * * Setup version upgrade procedure call order: * sp_vupgrade_replication -> sp_vupgrade_publisher -> sp_vupgrade_publisherdb -> sp_vupgrade_syscol_status */ set nocount on declare @artid int declare @src_objid int declare @columns binary(32) declare @this_col int declare @isset int -- raiserror('sp_vupgrade_syscol_status', 0,1) with nowait -- cursor through table based articles declare hCArt cursor local FAST_FORWARD for select artid, objid, columns from sysarticles where type & 1 = 1 open hCArt fetch hCArt into @artid, @src_objid, @columns while (@@fetch_status <> -1) begin -- cursor through columns on replicated object declare hCColid cursor local FAST_FORWARD for select colid from syscolumns where id = @src_objid open hCColid fetch hCColid into @this_col while (@@fetch_status <> -1) begin exec @isset = dbo.sp_isarticlecolbitset @this_col, @columns if @isset != 0 begin exec sp_MSarticlecol @artid, @this_col, 'publish', 'add' end fetch hCColid into @this_col end close hCColid deallocate hCColid fetch hCArt into @artid, @src_objid, @columns end close hCArt deallocate hCArt end go exec dbo.sp_MS_marksystemobject sp_vupgrade_syscol_status go raiserror('Creating procedure sp_vupgrade_publisherdb', 0,1) go create procedure sp_vupgrade_publisherdb @ver_old int, @ver_retention int as begin /* * Process schema and metadata changes specific to a publishing database. Transactional replication * system tables at the publisher are updated by sp_vupgrade_publisherdb; merge tables are not. * Most merge system tables exist in both the publishing and subscribing databases; merge schema * and metadata changes are processed by a separate pass over all databases in sp_vupgrade_mergetables. * * Match column order of newly created table when adding columns. * * Setup version upgrade procedure call order: * sp_vupgrade_replication -> sp_vupgrade_publisher -> sp_vupgrade_publisherdb */ set nocount on declare @default_name sysname -- raiserror('sp_vupgrade_publisherdb', 0,1) with nowait -- syssubscriptions if exists (select name from sysobjects where name='syssubscriptions') begin if not exists (select * from syscolumns where id = object_id('syssubscriptions') and name = 'queued_reinit') begin alter table syssubscriptions add queued_reinit bit default 0 not null end end -- end of syssubscriptions upgrade -- syspublications if exists (select name from sysobjects where name='syspublications') begin -- default_access column no longer used if exists (select * from syscolumns where id = object_id('syspublications') and name = 'default_access') begin alter table syspublications drop column default_access end /* * Queued updating subscriptions option; conflict management settings added later in this proc */ if not exists (select * from syscolumns where id = object_id('syspublications') and name = 'allow_queued_tran') begin alter table syspublications add allow_queued_tran bit default 0 not null end /* * Portable snapshot */ if not exists (select * from syscolumns where id = object_id('syspublications') and name = 'snapshot_in_defaultfolder') begin alter table syspublications add snapshot_in_defaultfolder bit default 1 not null end if not exists (select * from syscolumns where id = object_id('syspublications') and name = 'alt_snapshot_folder') begin alter table syspublications add alt_snapshot_folder nvarchar(255) null end /* * Snapshot pre/post commands */ if not exists (select * from syscolumns where id = object_id('syspublications') and name = 'pre_snapshot_script') begin alter table syspublications add pre_snapshot_script nvarchar(255) null end if not exists (select * from syscolumns where id = object_id('syspublications') and name = 'post_snapshot_script') begin alter table syspublications add post_snapshot_script nvarchar(255) null end /* * Snapshot compression */ if not exists (select * from syscolumns where id = object_id('syspublications') and name = 'compress_snapshot') begin alter table syspublications add compress_snapshot bit default 0 not null end /* * Post SQL7.0 FTP configuration stored at publisher */ if not exists (select * from syscolumns where id = object_id('syspublications') and name = 'ftp_address') begin alter table syspublications add ftp_address sysname null end if not exists (select * from syscolumns where id = object_id('syspublications') and name = 'ftp_port') begin alter table syspublications add ftp_port int not null default 21 end if not exists (select * from syscolumns where id = object_id('syspublications') and name = 'ftp_subdirectory') begin alter table syspublications add ftp_subdirectory nvarchar(255) null end if not exists (select * from syscolumns where id = object_id('syspublications') and name = 'ftp_login') begin alter table syspublications add ftp_login sysname null default N'anonymous' end if not exists (select * from syscolumns where id = object_id('syspublications') and name = 'ftp_password') begin alter table syspublications add ftp_password nvarchar(524) null end /* * Transformable subscriptions */ if not exists (select * from syscolumns where id = object_id('syspublications') and name = 'allow_dts') begin alter table syspublications add allow_dts bit default 0 not null end /* * Attach & Go */ if not exists (select * from syscolumns where id = object_id('syspublications') and name = 'allow_subscription_copy') begin alter table syspublications add allow_subscription_copy bit default 0 not null end /* * Transactional conflict management */ if not exists (select * from syscolumns where id = object_id('syspublications') and name = 'centralized_conflicts') begin alter table syspublications add centralized_conflicts bit NULL end if not exists (select * from syscolumns where id = object_id('syspublications') and name = 'conflict_retention') begin alter table syspublications add conflict_retention int NULL end if not exists (select * from syscolumns where id = object_id('syspublications') and name = 'conflict_policy') begin alter table syspublications add conflict_policy int NULL end /* * Attach & Go */ if not exists (select * from syscolumns where id = object_id('syspublications') and name = 'queue_type') begin alter table syspublications add queue_type int NULL end /* * Active Directory */ if not exists (select * from syscolumns where id = object_id('syspublications') and name = 'ad_guidname') begin alter table syspublications add ad_guidname sysname null end if not exists (select * from syscolumns where id = object_id('syspublications') and name = 'backward_comp_level') begin alter table syspublications add backward_comp_level int default 10 not null end /* * Schema only articles (views, procs, udfs) */ if not exists (select * from sysobjects where name = 'sysschemaarticles') begin create table dbo.sysschemaarticles ( artid int NOT NULL, creation_script nvarchar(255) NULL, description nvarchar(255) NULL, dest_object sysname NOT NULL, name sysname NOT NULL, objid int NOT NULL, pubid int NOT NULL, pre_creation_cmd tinyint NOT NULL, status int NOT NULL, type tinyint NOT NULL, schema_option binary(8) NULL, dest_owner sysname NULL ) exec dbo.sp_MS_marksystemobject sysschemaarticles if not exists (select * from sysindexes where name = 'unc1sysschemaarticles') begin create unique nonclustered index unc1sysschemaarticles on sysschemaarticles(artid, pubid) end end if exists (select * from sysobjects where name = 'sysextendedarticlesview') begin drop view dbo.sysextendedarticlesview end -- cannot create view directly in stored procedure exec ( 'create view dbo.sysextendedarticlesview as select artid, columns, creation_script, del_cmd, description, dest_table, filter, filter_clause, ins_cmd, name, objid, pubid, pre_creation_cmd, status, sync_objid, type, upd_cmd, schema_option, dest_owner from sysarticles union all select artid, NULL, creation_script, NULL, description, dest_object, NULL, NULL, NULL, name, objid, pubid, pre_creation_cmd, status, NULL, type, NULL, schema_option, dest_owner from sysschemaarticles' ) exec dbo.sp_MS_marksystemobject 'sysextendedarticlesview' exec sp_vupgrade_syscol_status end -- sysarticleupdates if exists (select name from sysobjects where name='sysarticleupdates') begin if not exists (select * from syscolumns where id = object_id('sysarticleupdates') and name = 'sync_upd_trig') begin alter table sysarticleupdates add sync_upd_trig int default 0 NOT NULL end if not exists (select * from syscolumns where id = object_id('sysarticleupdates') and name = 'conflict_tableid') begin alter table sysarticleupdates add conflict_tableid int NULL end if not exists (select * from syscolumns where id = object_id('sysarticleupdates') and name = 'ins_conflict_proc') begin alter table sysarticleupdates add ins_conflict_proc int NULL end if not exists (select * from syscolumns where id = object_id('sysarticleupdates') and name = 'identity_support') begin alter table sysarticleupdates add identity_support bit default 0 NOT NULL end end -- Upgrade dbt->distbackuplsn -- Make sure the upgrade is done for 8.0 Beta 2 customers. if exists (select * from sysobjects where name = 'sysarticles') and not exists (select * from sysobjects where name = 'systranschemas') begin -- Force to get in even if the logreader is running. exec sp_replflush exec sp_repldone @xactid = NULL, @xact_segno = NULL, @numtrans = 0, @time = 0, @reset = 0, @code = 1 -- Unmark the connection as the logreader. exec sp_replflush end -- Create new tran tables if the db is enabled for tran publishing. if exists (select name from sysobjects where name='syspublications') begin exec dbo.sp_MScreate_pub_tables end /* * syspublications */ if exists (select name from sysobjects where name='syspublications') begin if not exists (select * from syscolumns where id = Object_Id('syspublications') and name = 'ftp_password' and length = '1048') begin /* * syspublications ftp_password * no need to upgrade passwords since this column is new in 8.0. */ declare @dbname sysname declare @cmptlevel tinyint set @dbname = db_name() select @cmptlevel = cmptlevel from master..sysdatabases where name = @dbname collate database_default if @cmptlevel < 70 begin raiserror (15048, -1, -1, 70, 70, 70, 80) end else begin exec( 'alter table syspublications alter column ftp_password nvarchar(524)' ) end end -- change non-clustered index on syspublications.pubid to clustered -- index if exists( select * from sysindexes where name = 'unc1syspublications' and id = object_id('dbo.syspublications') ) begin drop index dbo.syspublications.unc1syspublications end if not exists ( select * from sysindexes where name = 'uc1syspublications' and id = object_id('dbo.syspublications') ) begin create unique clustered index uc1syspublications on syspublications (pubid) end end end go exec dbo.sp_MS_marksystemobject sp_vupgrade_publisherdb go raiserror('Creating procedure sp_vupgrade_replmsdb', 0,1) go create procedure sp_vupgrade_replmsdb as begin /* * Process schema and metadata changes specific to a msdb database. Updates datatype * mappings for heterogeneous replication. * * Setup version upgrade procedure call order: * sp_vupgrade_replication -> sp_vupgrade_replmsdb (only called at distributors) */ set nocount on declare @retcode int ,@profile_id int ,@table_name sysname ,@profile_name nvarchar(100) ,@profile_desc nvarchar(100) -- raiserror('sp_vupgrade_replmsdb', 0,1) -- Drop and regenerate agent parameters and associated values from system profiles. select @profile_id = 1 while (@profile_id < 8) begin exec @retcode = dbo.sp_drop_agent_parameter @profile_id if (@retcode = 1) return (1) exec @retcode = dbo.sp_generate_agent_parameter @profile_id if (@retcode = 1) return (1) select @profile_id = @profile_id + 1 end declare hUserProfile CURSOR LOCAL FAST_FORWARD FOR select distinct profile_id from msdb..MSagent_profiles where profile_id >= 8 for read only open hUserProfile fetch hUserProfile into @profile_id while @@fetch_status <> -1 begin exec @retcode = dbo.sp_drop_agent_parameter @profile_id, @parameter_name = '-ReadBatchThreshold' if (@retcode = 1) begin close hUserProfile deallocate hUserProfile return (1) end fetch hUserProfile into @profile_id end close hUserProfile deallocate hUserProfile -- -- Add 8.0 agent profiles -- /* ** Distribution agent : Synchronization Manager Profile */ select @profile_id = NULL ,@profile_name = formatmessage(20550) -- Dist SyncMgr Profile ,@profile_desc = formatmessage(20551) select @profile_id = profile_id from msdb..MSagent_profiles where agent_type = 3 and profile_name = @profile_name if (@profile_id is null) begin -- -- Add profile -- select @profile_id = NULL exec @retcode = dbo.sp_add_agent_profile @profile_id = @profile_id OUT, @profile_name = @profile_name, @agent_type = 3, -- 1-Snapshot, 2-Logreader, 3-Distribution, 4-Merge @profile_type = 0, -- 0-System, 1-Custom @description = @profile_desc, @default = 0 if (@retcode = 1 or @@ERROR <> 0) return (1) end else begin -- -- Profile exists - drop the parameters for regeneration -- exec @retcode = dbo.sp_drop_agent_parameter @profile_id if (@retcode = 1) return (1) end exec @retcode = dbo.sp_generate_agent_parameter @profile_id = 10, @real_profile_id = @profile_id if (@retcode = 1 or @@ERROR <> 0) return (1) -- Queue default profile select @profile_id = NULL select @profile_id = profile_id from msdb..MSagent_profiles where agent_type = 9 and def_profile = 1 if (@profile_id is null) begin -- -- Add profile -- select @profile_id = NULL ,@profile_name = formatmessage(20545) -- Default QueueReader Profile ,@profile_desc = formatmessage(20589) exec @retcode = dbo.sp_add_agent_profile @profile_id = @profile_id OUT, @profile_name = @profile_name, @agent_type = 9, @profile_type = 0, @description = @profile_desc, @default = 1 if (@retcode = 1 or @@ERROR <> 0) return (1) end else begin -- -- Profile exists - drop the parameters for regeneration -- exec @retcode = dbo.sp_drop_agent_parameter @profile_id if (@retcode = 1) return (1) end exec @retcode = dbo.sp_generate_agent_parameter @profile_id = 11, @real_profile_id = @profile_id if (@retcode = 1 or @@ERROR <> 0) return (1) -- -- Add 'skip data consistency error' profile -- select @profile_id = NULL ,@profile_name = formatmessage(20599) -- Default Distribution Profile ,@profile_desc = formatmessage(20600) select @profile_id = profile_id from msdb..MSagent_profiles where agent_type = 3 and profile_name = @profile_name if (@profile_id is null) begin -- -- Add profile -- select @profile_id = NULL exec @retcode = dbo.sp_add_agent_profile @profile_id = @profile_id OUT, @profile_name = @profile_name, @agent_type = 3, -- 1-Snapshot, 2-Logreader, 3-Distribution, 4-Merge @profile_type = 0, -- 0-System, 1-Custom @description = @profile_desc, @default = 0 if (@retcode = 1 or @@ERROR <> 0) return (1) end else begin -- -- Profile exists - drop the parameters for regeneration -- exec @retcode = dbo.sp_drop_agent_parameter @profile_id if (@retcode = 1) return (1) end exec @retcode = dbo.sp_generate_agent_parameter @profile_id = 14, @real_profile_id = @profile_id if (@retcode = 1 or @@ERROR <> 0) return (1) /* ** Merge agent : Non default profile for disconnected scenarios ( unreliable link ) */ set @profile_id = NULL set @profile_name = formatmessage(20548) -- Non-Default Merge Profile set @profile_desc = formatmessage(20549) select @profile_id = profile_id from msdb..MSagent_profiles where agent_type = 4 and profile_name = @profile_name if (@profile_id is null) begin exec @retcode = dbo.sp_add_agent_profile @profile_id = @profile_id OUT, @profile_name = @profile_name, @agent_type = 4, -- 1-Snapshot, 2-Logreader, 3-Distribution, 4-Merge @profile_type = 0, -- 0-System, 1-Custom @description = @profile_desc, @default = 0 end else begin -- -- Profile exists - drop the parameters for regeneration -- exec @retcode = dbo.sp_drop_agent_parameter @profile_id if (@retcode = 1) return (1) end exec @retcode = dbo.sp_generate_agent_parameter 7, @profile_id if (@retcode = 1 or @@ERROR <> 0) return (1) /* ** Merge agent : Non default profile for verbose histroy */ set @profile_id = NULL set @profile_name = formatmessage(20546) -- Verbose Merge Profile set @profile_desc = formatmessage(20547) select @profile_id = profile_id from msdb..MSagent_profiles where agent_type = 4 and profile_name = @profile_name if (@profile_id is null) begin exec @retcode = dbo.sp_add_agent_profile @profile_id = @profile_id OUT, @profile_name = @profile_name, @agent_type = 4, -- 1-Snapshot, 2-Logreader, 3-Distribution, 4-Merge @profile_type = 0, -- 0-System, 1-Custom @description = @profile_desc, @default = 0 end else begin -- -- Profile exists - drop the parameters for regeneration -- exec @retcode = dbo.sp_drop_agent_parameter @profile_id if (@retcode = 1) return (1) end exec @retcode = dbo.sp_generate_agent_parameter 8, @profile_id if (@retcode = 1 or @@ERROR <> 0) return (1) /* ** Merge agent : Synchronization Manager Profile */ set @profile_id = NULL set @profile_name = formatmessage(20550) -- SyncMgr Profile set @profile_desc = formatmessage(20551) select @profile_id = profile_id from msdb..MSagent_profiles where agent_type = 4 and profile_name = @profile_name if (@profile_id is null) begin exec @retcode = dbo.sp_add_agent_profile @profile_id = @profile_id OUT, @profile_name = @profile_name, @agent_type = 4, -- 1-Snapshot, 2-Logreader, 3-Distribution, 4-Merge @profile_type = 0, -- 0-System, 1-Custom @description = @profile_desc, @default = 0 end else begin -- -- Profile exists - drop the parameters for regeneration -- exec @retcode = dbo.sp_drop_agent_parameter @profile_id if (@retcode = 1) return (1) end exec @retcode = dbo.sp_generate_agent_parameter 9, @profile_id if (@retcode = 1 or @@ERROR <> 0) return (1) /* ** Merge agent : Rowcount Validation profile */ set @profile_id = NULL set @profile_name = formatmessage(21308) -- Rowcount Validation Profile set @profile_desc = formatmessage(21309) -- Rowcount Validation Profile Description select @profile_id = profile_id from msdb..MSagent_profiles where agent_type = 4 and profile_name = @profile_name if (@profile_id is null) begin exec @retcode = dbo.sp_add_agent_profile @profile_id = @profile_id OUT, @profile_name = @profile_name, @agent_type = 4, -- 1-Snapshot, 2-Logreader, 3-Distribution, 4-Merge @profile_type = 0, -- 0-System, 1-Custom @description = @profile_desc, @default = 0 end else begin -- -- Profile exists - drop the parameters for regeneration -- exec @retcode = dbo.sp_drop_agent_parameter @profile_id if (@retcode = 1) return (1) end exec @retcode = dbo.sp_generate_agent_parameter 12, @profile_id if (@retcode = 1 or @@ERROR <> 0) return (1) /* ** Merge agent : Rowcount & Checksum Validation profile */ set @profile_id = NULL set @profile_name = formatmessage(21310) -- Rowcount & Checksum Validation Profile set @profile_desc = formatmessage(21311) -- Rowcount & Checksum Validation Profile Description select @profile_id = profile_id from msdb..MSagent_profiles where agent_type = 4 and profile_name = @profile_name if (@profile_id is null) begin exec @retcode = dbo.sp_add_agent_profile @profile_id = @profile_id OUT, @profile_name = @profile_name, @agent_type = 4, -- 1-Snapshot, 2-Logreader, 3-Distribution, 4-Merge @profile_type = 0, -- 0-System, 1-Custom @description = @profile_desc, @default = 0 end else begin -- -- Profile exists - drop the parameters for regeneration -- exec @retcode = dbo.sp_drop_agent_parameter @profile_id if (@retcode = 1) return (1) end exec @retcode = dbo.sp_generate_agent_parameter 13, @profile_id if (@retcode = 1 or @@ERROR <> 0) return (1) /* ** Merge agent : High volume server-to-server profile */ set @profile_id = NULL set @profile_name = formatmessage(20616) -- High volume server-to-server profile set @profile_desc = formatmessage(20617) -- High volume server-to-server profile Description select @profile_id = profile_id from msdb..MSagent_profiles where agent_type = 4 and profile_name = @profile_name if (@profile_id is null) begin exec @retcode = dbo.sp_add_agent_profile @profile_id = @profile_id OUT, @profile_name = @profile_name, @agent_type = 4, -- 1-Snapshot, 2-Logreader, 3-Distribution, 4-Merge @profile_type = 0, -- 0-System, 1-Custom @description = @profile_desc, @default = 0 end else begin -- -- Profile exists - drop the parameters for regeneration -- exec @retcode = dbo.sp_drop_agent_parameter @profile_id if (@retcode = 1) return (1) end exec @retcode = dbo.sp_generate_agent_parameter 15, @profile_id if (@retcode = 1 or @@ERROR <> 0) return (1) -- Add MSdatatype_mappings table and default mappings if not exists( select * from msdb..sysobjects where name = 'MSdatatype_mappings' and xtype = 'U') begin create table msdb.dbo.MSdatatype_mappings ( dbms_name sysname NOT NULL, sql_type sysname NOT NULL, dest_type sysname NOT NULL, dest_prec int NOT NULL, dest_create_params int NOT NULL, dest_nullable bit NOT NULL ) -- MS Jet exec dbo.sp_add_datatype_mapping 'MS Jet', 'binary' , 'binary', 255, 4, 1 exec dbo.sp_add_datatype_mapping 'MS Jet', 'varbinary' , 'varbinary', 255, 4, 1 exec dbo.sp_add_datatype_mapping 'MS Jet', 'binary' , 'image', 1073741824, 0, 1 exec dbo.sp_add_datatype_mapping 'MS Jet', 'varbinary' , 'image', 1073741824, 0, 1 exec dbo.sp_add_datatype_mapping 'MS Jet', 'sql_variant' , 'longtext', 1073741824, 0, 1 exec dbo.sp_add_datatype_mapping 'MS Jet', 'varchar' , 'varchar', 255, 4, 1 exec dbo.sp_add_datatype_mapping 'MS Jet', 'varchar' , 'longtext', 1073741824, 0, 1 exec dbo.sp_add_datatype_mapping 'MS Jet', 'nchar' , 'nchar', 255, 4, 1 exec dbo.sp_add_datatype_mapping 'MS Jet', 'nchar' , 'longtext', 1073741824, 0, 1 exec dbo.sp_add_datatype_mapping 'MS Jet', 'char' , 'char', 255, 4, 1 exec dbo.sp_add_datatype_mapping 'MS Jet', 'char' , 'longtext', 1073741824, 0, 1 exec dbo.sp_add_datatype_mapping 'MS Jet', 'nvarchar' , 'nchar varying', 255, 4, 1 exec dbo.sp_add_datatype_mapping 'MS Jet', 'nvarchar' , 'longtext', 1073741824, 0, 1 exec dbo.sp_add_datatype_mapping 'MS Jet', 'datetime' , 'datetime', 255, 0, 1 exec dbo.sp_add_datatype_mapping 'MS Jet', 'smalldatetime' , 'datetime', 255, 0, 1 exec dbo.sp_add_datatype_mapping 'MS Jet', 'decimal' , 'decimal', 255, 3, 1 exec dbo.sp_add_datatype_mapping 'MS Jet', 'numeric' , 'decimal', 255, 3, 1 exec dbo.sp_add_datatype_mapping 'MS Jet', 'float' , 'float', 255, 0, 1 exec dbo.sp_add_datatype_mapping 'MS Jet', 'real' , 'real', 255, 0, 1 exec dbo.sp_add_datatype_mapping 'MS Jet', 'bigint' , 'decimal', 255, 0, 1 exec dbo.sp_add_datatype_mapping 'MS Jet', 'int' , 'int', 255, 0, 1 exec dbo.sp_add_datatype_mapping 'MS Jet', 'smallint' , 'smallint', 255, 0, 1 exec dbo.sp_add_datatype_mapping 'MS Jet', 'tinyint' , 'byte', 255, 0, 1 exec dbo.sp_add_datatype_mapping 'MS Jet', 'money' , 'currency', 255, 0, 1 exec dbo.sp_add_datatype_mapping 'MS Jet', 'smallmoney' , 'currency', 255, 0, 1 exec dbo.sp_add_datatype_mapping 'MS Jet', 'bit' , 'bit', 255, 0, 1 exec dbo.sp_add_datatype_mapping 'MS Jet', 'sysname' , 'nchar varying', 255, 4, 1 exec dbo.sp_add_datatype_mapping 'MS Jet', 'timestamp' , 'binary', 255, 4, 1 exec dbo.sp_add_datatype_mapping 'MS Jet', 'uniqueidentifier' , 'guid', 255, 0, 1 exec dbo.sp_add_datatype_mapping 'MS Jet', 'text' , 'longtext', 1073741824, 0, 1 exec dbo.sp_add_datatype_mapping 'MS Jet', 'ntext' , 'longtext', 1073741824, 0, 1 exec dbo.sp_add_datatype_mapping 'MS Jet', 'image' , 'image', 1073741824, 0, 1 -- Oracle exec dbo.sp_add_datatype_mapping 'Oracle', 'binary' , 'raw', 255, 4, 1 exec dbo.sp_add_datatype_mapping 'Oracle', 'varbinary' , 'raw', 255, 4, 1 exec dbo.sp_add_datatype_mapping 'Oracle', 'binary' , 'long raw', 2147483647, 0, 1 exec dbo.sp_add_datatype_mapping 'Oracle', 'varbinary' , 'long raw', 2147483647, 0, 1 exec dbo.sp_add_datatype_mapping 'Oracle', 'sql_variant' , 'long', 2147483647, 0, 1 --exec dbo.sp_add_datatype_mapping 'Oracle', 'varchar' , 'char', 255, 4, 1 exec dbo.sp_add_datatype_mapping 'Oracle', 'varchar' , 'varchar2', 2000, 4, 1 exec dbo.sp_add_datatype_mapping 'Oracle', 'varchar' , 'long', 2147483647, 0, 1 exec dbo.sp_add_datatype_mapping 'Oracle', 'nchar' , 'char', 255, 4, 1 exec dbo.sp_add_datatype_mapping 'Oracle', 'nchar' , 'varchar2', 2000, 4, 1 exec dbo.sp_add_datatype_mapping 'Oracle', 'nchar' , 'long', 2147483647, 0, 1 exec dbo.sp_add_datatype_mapping 'Oracle', 'char' , 'char', 255, 4, 1 exec dbo.sp_add_datatype_mapping 'Oracle', 'char' , 'varchar2', 2000, 4, 1 exec dbo.sp_add_datatype_mapping 'Oracle', 'char' , 'long', 2147483647, 0, 1 --exec dbo.sp_add_datatype_mapping 'Oracle', 'nvarchar' , 'char', 255, 4, 1 exec dbo.sp_add_datatype_mapping 'Oracle', 'nvarchar' , 'varchar2', 2000, 4, 1 exec dbo.sp_add_datatype_mapping 'Oracle', 'nvarchar' , 'long', 2147483647, 0, 1 exec dbo.sp_add_datatype_mapping 'Oracle', 'datetime' , 'date', 255, 0, 1 exec dbo.sp_add_datatype_mapping 'Oracle', 'smalldatetime' , 'date', 255, 0, 1 exec dbo.sp_add_datatype_mapping 'Oracle', 'decimal' , 'number', 255, 3, 1 exec dbo.sp_add_datatype_mapping 'Oracle', 'numeric' , 'number', 255, 3, 1 exec dbo.sp_add_datatype_mapping 'Oracle', 'float' , 'float', 255, 0, 1 exec dbo.sp_add_datatype_mapping 'Oracle', 'real' , 'float', 255, 0, 1 exec dbo.sp_add_datatype_mapping 'Oracle', 'bigint' , 'number', 255, 3, 1 exec dbo.sp_add_datatype_mapping 'Oracle', 'int' , 'number', 255, 3, 1 exec dbo.sp_add_datatype_mapping 'Oracle', 'smallint' , 'number', 255, 3, 1 exec dbo.sp_add_datatype_mapping 'Oracle', 'tinyint' , 'number', 255, 3, 1 exec dbo.sp_add_datatype_mapping 'Oracle', 'money' , 'number', 255, 3, 1 exec dbo.sp_add_datatype_mapping 'Oracle', 'smallmoney' , 'number', 255, 3, 1 exec dbo.sp_add_datatype_mapping 'Oracle', 'bit' , 'number', 255, 3, 1 exec dbo.sp_add_datatype_mapping 'Oracle', 'sysname' , 'char', 255, 4, 1 exec dbo.sp_add_datatype_mapping 'Oracle', 'timestamp' , 'raw', 255, 4, 1 exec dbo.sp_add_datatype_mapping 'Oracle', 'uniqueidentifier' , 'char', 255, 4, 1 exec dbo.sp_add_datatype_mapping 'Oracle', 'text' , 'long', 2147483647, 0, 1 exec dbo.sp_add_datatype_mapping 'Oracle', 'ntext' , 'long', 2147483647, 0, 1 exec dbo.sp_add_datatype_mapping 'Oracle', 'image' , 'long raw', 2147483647, 0, 1 -- MS SSCE exec dbo.sp_add_datatype_mapping 'MS SSCE', 'binary' , 'binary', 255, 4, 1 exec dbo.sp_add_datatype_mapping 'MS SSCE', 'varbinary' , 'varbinary', 255, 4, 1 exec dbo.sp_add_datatype_mapping 'MS SSCE', 'binary' , 'image', 1073741824, 0, 1 exec dbo.sp_add_datatype_mapping 'MS SSCE', 'varbinary' , 'image', 1073741824, 0, 1 exec dbo.sp_add_datatype_mapping 'MS SSCE', 'sql_variant' , 'ntext', 1073741824, 0, 1 exec dbo.sp_add_datatype_mapping 'MS SSCE', 'varchar' , 'national char varying', 255, 4, 1 exec dbo.sp_add_datatype_mapping 'MS SSCE', 'varchar' , 'ntext', 1073741824, 0, 1 exec dbo.sp_add_datatype_mapping 'MS SSCE', 'nchar' , 'nchar', 255, 4, 1 exec dbo.sp_add_datatype_mapping 'MS SSCE', 'nchar' , 'ntext', 1073741824, 0, 1 exec dbo.sp_add_datatype_mapping 'MS SSCE', 'char' , 'nchar', 255, 4, 1 exec dbo.sp_add_datatype_mapping 'MS SSCE', 'char' , 'ntext', 1073741824, 0, 1 exec dbo.sp_add_datatype_mapping 'MS SSCE', 'nvarchar' , 'national char varying', 255, 4, 1 exec dbo.sp_add_datatype_mapping 'MS SSCE', 'nvarchar' , 'ntext', 1073741824, 0, 1 exec dbo.sp_add_datatype_mapping 'MS SSCE', 'datetime' , 'datetime', 255, 0, 1 exec dbo.sp_add_datatype_mapping 'MS SSCE', 'smalldatetime' , 'datetime', 255, 0, 1 exec dbo.sp_add_datatype_mapping 'MS SSCE', 'decimal' , 'numeric', 255, 3, 1 exec dbo.sp_add_datatype_mapping 'MS SSCE', 'numeric' , 'numeric', 255, 3, 1 exec dbo.sp_add_datatype_mapping 'MS SSCE', 'float' , 'float', 255, 0, 1 exec dbo.sp_add_datatype_mapping 'MS SSCE', 'real' , 'real', 255, 0, 1 exec dbo.sp_add_datatype_mapping 'MS SSCE', 'bigint' , 'bigint', 255, 0, 1 exec dbo.sp_add_datatype_mapping 'MS SSCE', 'int' , 'int', 255, 0, 1 exec dbo.sp_add_datatype_mapping 'MS SSCE', 'smallint' , 'smallint', 255, 0, 1 exec dbo.sp_add_datatype_mapping 'MS SSCE', 'tinyint' , 'tinyint', 255, 0, 1 exec dbo.sp_add_datatype_mapping 'MS SSCE', 'money' , 'money', 255, 0, 1 exec dbo.sp_add_datatype_mapping 'MS SSCE', 'smallmoney' , 'money', 255, 0, 1 exec dbo.sp_add_datatype_mapping 'MS SSCE', 'bit' , 'bit', 255, 0, 1 exec dbo.sp_add_datatype_mapping 'MS SSCE', 'sysname' , 'national char varying', 255, 4, 1 exec dbo.sp_add_datatype_mapping 'MS SSCE', 'timestamp' , 'binary', 255, 4, 1 exec dbo.sp_add_datatype_mapping 'MS SSCE', 'uniqueidentifier' , 'uniqueidentifier', 255, 0, 1 exec dbo.sp_add_datatype_mapping 'MS SSCE', 'text' , 'ntext', 1073741824, 0, 1 exec dbo.sp_add_datatype_mapping 'MS SSCE', 'ntext' , 'ntext', 1073741824, 0, 1 exec dbo.sp_add_datatype_mapping 'MS SSCE', 'image' , 'image', 1073741824, 0, 1 --DB2/400 exec dbo.sp_add_datatype_mapping 'DB2/400', 'bit', 'SMALLINT', 1, 0, 1 exec dbo.sp_add_datatype_mapping 'DB2/400', 'tinyint', 'SMALLINT', 1, 0, 1 exec dbo.sp_add_datatype_mapping 'DB2/400', 'smallint', 'SMALLINT', 5, 0, 1 exec dbo.sp_add_datatype_mapping 'DB2/400', 'int', 'INT', 10, 0, 1 exec dbo.sp_add_datatype_mapping 'DB2/400', 'char', 'CHAR', 8000, 4, 1 exec dbo.sp_add_datatype_mapping 'DB2/400', 'varchar', 'VARCHAR', 8000, 4, 1 exec dbo.sp_add_datatype_mapping 'DB2/400', 'smalldatetime', 'TIMESTAMP', 26, 0, 1 exec dbo.sp_add_datatype_mapping 'DB2/400', 'datetime', 'TIMESTAMP', 26, 0, 1 exec dbo.sp_add_datatype_mapping 'DB2/400', 'real', 'REAL', 24, 0, 1 exec dbo.sp_add_datatype_mapping 'DB2/400', 'decimal', 'DECIMAL', 31, 3, 1 exec dbo.sp_add_datatype_mapping 'DB2/400', 'double precision', 'DOUBLE', 53, 0, 1 exec dbo.sp_add_datatype_mapping 'DB2/400', 'float', 'FLOAT', 53, 0, 1 exec dbo.sp_add_datatype_mapping 'DB2/400', 'numeric', 'NUMERIC', 31, 3, 1 exec dbo.sp_add_datatype_mapping 'DB2/400', 'smallmoney', 'DECIMAL', 10, 3, 1 exec dbo.sp_add_datatype_mapping 'DB2/400', 'money', 'DECIMAL', 19, 3, 1 exec dbo.sp_add_datatype_mapping 'DB2/400', 'varbinary', 'VARCHAR () FOR BIT DATA', 8000, 4, 1 exec dbo.sp_add_datatype_mapping 'DB2/400', 'binary', 'CHAR () FOR BIT DATA', 8000, 4, 1 exec dbo.sp_add_datatype_mapping 'DB2/400', 'timestamp', 'CHAR () FOR BIT DATA', 8, 4, 1 exec dbo.sp_add_datatype_mapping 'DB2/400', 'uniqueidentifier', 'CHAR', 38, 4, 1 exec dbo.sp_add_datatype_mapping 'DB2/400', 'image', 'VARCHAR () FOR BIT DATA', 32739, 4, 1 exec dbo.sp_add_datatype_mapping 'DB2/400', 'text', 'VARCHAR', 32739, 4, 1 --DB2/MVS exec dbo.sp_add_datatype_mapping 'DB2/MVS', 'bit', 'SMALLINT', 1, 0, 1 exec dbo.sp_add_datatype_mapping 'DB2/MVS', 'tinyint', 'SMALLINT', 1, 0, 1 exec dbo.sp_add_datatype_mapping 'DB2/MVS', 'smallint', 'SMALLINT', 5, 0, 1 exec dbo.sp_add_datatype_mapping 'DB2/MVS', 'int', 'INT', 10, 0, 1 exec dbo.sp_add_datatype_mapping 'DB2/MVS', 'char', 'CHAR', 254, 4, 1 exec dbo.sp_add_datatype_mapping 'DB2/MVS', 'varchar', 'VARCHAR', 4045, 4, 1 exec dbo.sp_add_datatype_mapping 'DB2/MVS', 'char', 'VARCHAR', 4045, 4, 1 exec dbo.sp_add_datatype_mapping 'DB2/MVS', 'smalldatetime', 'TIMESTAMP', 26, 0, 1 exec dbo.sp_add_datatype_mapping 'DB2/MVS', 'datetime', 'TIMESTAMP', 26, 0, 1 exec dbo.sp_add_datatype_mapping 'DB2/MVS', 'real', 'REAL', 24, 0, 1 exec dbo.sp_add_datatype_mapping 'DB2/MVS', 'decimal', 'DECIMAL', 31, 3, 1 exec dbo.sp_add_datatype_mapping 'DB2/MVS', 'double precision', 'DOUBLE', 53, 0, 1 exec dbo.sp_add_datatype_mapping 'DB2/MVS', 'float', 'FLOAT', 53, 0, 1 exec dbo.sp_add_datatype_mapping 'DB2/MVS', 'numeric', 'NUMERIC', 31, 3, 1 exec dbo.sp_add_datatype_mapping 'DB2/MVS', 'smallmoney', 'DECIMAL', 10, 3, 1 exec dbo.sp_add_datatype_mapping 'DB2/MVS', 'money', 'DECIMAL', 19, 3, 1 exec dbo.sp_add_datatype_mapping 'DB2/MVS', 'varbinary', 'VARCHAR () FOR BIT DATA', 4045, 4, 1 exec dbo.sp_add_datatype_mapping 'DB2/MVS', 'binary', 'CHAR () FOR BIT DATA', 254, 4, 1 exec dbo.sp_add_datatype_mapping 'DB2/MVS', 'timestamp', 'CHAR () FOR BIT DATA', 8, 4, 1 exec dbo.sp_add_datatype_mapping 'DB2/MVS', 'uniqueidentifier', 'CHAR', 38, 4, 1 exec dbo.sp_add_datatype_mapping 'DB2/MVS', 'image', 'VARCHAR () FOR BIT DATA', 4045, 4, 1 exec dbo.sp_add_datatype_mapping 'DB2/MVS', 'text', 'VARCHAR', 4045, 4, 1 --DB2/NT exec dbo.sp_add_datatype_mapping 'DB2/NT', 'bit', 'SMALLINT', 1, 0, 1 exec dbo.sp_add_datatype_mapping 'DB2/NT', 'tinyint', 'SMALLINT', 1, 0, 1 exec dbo.sp_add_datatype_mapping 'DB2/NT', 'smallint', 'SMALLINT', 5, 0, 1 exec dbo.sp_add_datatype_mapping 'DB2/NT', 'int', 'INT', 10, 0, 1 exec dbo.sp_add_datatype_mapping 'DB2/NT', 'char', 'CHAR', 254, 4, 1 exec dbo.sp_add_datatype_mapping 'DB2/NT', 'varchar', 'VARCHAR', 4000, 4, 1 exec dbo.sp_add_datatype_mapping 'DB2/NT', 'char', 'VARCHAR', 4000, 4, 1 exec dbo.sp_add_datatype_mapping 'DB2/NT', 'smalldatetime', 'TIMESTAMP', 26, 0, 1 exec dbo.sp_add_datatype_mapping 'DB2/NT', 'datetime', 'TIMESTAMP', 26, 0, 1 exec dbo.sp_add_datatype_mapping 'DB2/NT', 'real', 'REAL', 24, 0, 1 exec dbo.sp_add_datatype_mapping 'DB2/NT', 'decimal', 'DECIMAL', 31, 3, 1 exec dbo.sp_add_datatype_mapping 'DB2/NT', 'double precision', 'DOUBLE', 53, 0, 1 exec dbo.sp_add_datatype_mapping 'DB2/NT', 'float', 'FLOAT', 53, 0, 1 exec dbo.sp_add_datatype_mapping 'DB2/NT', 'numeric', 'NUMERIC', 31, 3, 1 exec dbo.sp_add_datatype_mapping 'DB2/NT', 'smallmoney', 'DECIMAL', 10, 3, 1 exec dbo.sp_add_datatype_mapping 'DB2/NT', 'money', 'DECIMAL', 19, 3, 1 exec dbo.sp_add_datatype_mapping 'DB2/NT', 'varbinary', 'VARCHAR () FOR BIT DATA', 4000, 4, 1 exec dbo.sp_add_datatype_mapping 'DB2/NT', 'binary', 'CHAR () FOR BIT DATA', 254, 4, 1 exec dbo.sp_add_datatype_mapping 'DB2/NT', 'timestamp', 'CHAR () FOR BIT DATA', 8, 4, 1 exec dbo.sp_add_datatype_mapping 'DB2/NT', 'uniqueidentifier', 'CHAR', 38, 4, 1 exec dbo.sp_add_datatype_mapping 'DB2/NT', 'image', 'VARCHAR () FOR BIT DATA', 4000, 4, 1 exec dbo.sp_add_datatype_mapping 'DB2/NT', 'text', 'VARCHAR', 4000, 4, 1 --DB2/6000 exec dbo.sp_add_datatype_mapping 'DB2/6000', 'bit', 'SMALLINT', 1, 0, 1 exec dbo.sp_add_datatype_mapping 'DB2/6000', 'tinyint', 'SMALLINT', 1, 0, 1 exec dbo.sp_add_datatype_mapping 'DB2/6000', 'smallint', 'SMALLINT', 5, 0, 1 exec dbo.sp_add_datatype_mapping 'DB2/6000', 'int', 'INT', 10, 0, 1 exec dbo.sp_add_datatype_mapping 'DB2/6000', 'char', 'CHAR', 254, 4, 1 exec dbo.sp_add_datatype_mapping 'DB2/6000', 'varchar', 'VARCHAR', 4000, 4, 1 exec dbo.sp_add_datatype_mapping 'DB2/6000', 'char', 'VARCHAR', 4000, 4, 1 exec dbo.sp_add_datatype_mapping 'DB2/6000', 'smalldatetime', 'TIMESTAMP', 26, 0, 1 exec dbo.sp_add_datatype_mapping 'DB2/6000', 'datetime', 'TIMESTAMP', 26, 0, 1 exec dbo.sp_add_datatype_mapping 'DB2/6000', 'real', 'REAL', 24, 0, 1 exec dbo.sp_add_datatype_mapping 'DB2/6000', 'decimal', 'DECIMAL', 31, 3, 1 exec dbo.sp_add_datatype_mapping 'DB2/6000', 'double precision', 'DOUBLE', 53, 0, 1 exec dbo.sp_add_datatype_mapping 'DB2/6000', 'float', 'FLOAT', 53, 0, 1 exec dbo.sp_add_datatype_mapping 'DB2/6000', 'numeric', 'NUMERIC', 31, 3, 1 exec dbo.sp_add_datatype_mapping 'DB2/6000', 'smallmoney', 'DECIMAL', 10, 3, 1 exec dbo.sp_add_datatype_mapping 'DB2/6000', 'money', 'DECIMAL', 19, 3, 1 exec dbo.sp_add_datatype_mapping 'DB2/6000', 'varbinary', 'VARCHAR () FOR BIT DATA', 4000, 4, 1 exec dbo.sp_add_datatype_mapping 'DB2/6000', 'binary', 'CHAR () FOR BIT DATA', 254, 4, 1 exec dbo.sp_add_datatype_mapping 'DB2/6000', 'timestamp', 'CHAR () FOR BIT DATA', 8, 4, 1 exec dbo.sp_add_datatype_mapping 'DB2/6000', 'uniqueidentifier', 'CHAR', 38, 4, 1 exec dbo.sp_add_datatype_mapping 'DB2/6000', 'image', 'VARCHAR () FOR BIT DATA', 4000, 4, 1 exec dbo.sp_add_datatype_mapping 'DB2/6000', 'text', 'VARCHAR', 4000, 4, 1 end /* * New indexes added starting with 7.0 sp1 */ -- MSdistpublishers select @table_name = N'MSdistpublishers' IF EXISTS ( SELECT * FROM msdb.dbo.sysobjects WHERE name = 'MSdistpublishers' ) BEGIN IF EXISTS ( SELECT name FROM msdb.dbo.MSdistpublishers GROUP BY name HAVING COUNT(*) > 1 ) RAISERROR (21203, 10, 19, @table_name) ELSE IF NOT EXISTS ( SELECT * FROM msdb.dbo.sysindexes WHERE name = 'uc1MSdistpublishers' AND id = OBJECT_ID('msdb.dbo.MSdistpublishers') ) CREATE UNIQUE CLUSTERED INDEX uc1MSdistpublishers ON msdb.dbo.MSdistpublishers(name) END -- MSdistributiondbs SELECT @table_name = N'MSdistributiondbs' IF EXISTS ( SELECT * FROM msdb.dbo.sysobjects WHERE name = 'MSdistributiondbs' ) BEGIN IF EXISTS ( SELECT name FROM msdb.dbo.MSdistributiondbs GROUP BY name HAVING COUNT(*) > 1 ) RAISERROR (21203, 10, 20, @table_name) ELSE IF NOT EXISTS ( SELECT * FROM msdb.dbo.sysindexes WHERE name = 'uc1MSdistributiondbs' AND id = OBJECT_ID('msdb.dbo.MSdistributiondbs') ) CREATE UNIQUE CLUSTERED INDEX uc1MSdistributiondbs ON msdb.dbo.MSdistributiondbs(name) END -- MSdistributor SELECT @table_name = N'MSdistributor' IF EXISTS ( SELECT * FROM msdb.dbo.sysobjects WHERE name = 'MSdistributor' ) BEGIN IF EXISTS ( SELECT property FROM msdb.dbo.MSdistributor GROUP BY property HAVING COUNT(*) > 1 ) RAISERROR (21203, 10, 21, @table_name) ELSE IF NOT EXISTS ( SELECT * FROM msdb.dbo.sysindexes WHERE name = 'uc1MSdistributor' AND id = OBJECT_ID('msdb.dbo.MSdistributor') ) CREATE UNIQUE CLUSTERED INDEX uc1MSdistributor ON msdb.dbo.MSdistributor(property) END /* * Upgrade replication passwords in msdb database. */ begin transaction /* * MSdistpublishers */ if exists (select name from msdb.dbo.sysobjects where name='MSdistpublishers') begin if not exists (select * from msdb.dbo.syscolumns where id = Object_Id('msdb.dbo.MSdistpublishers') and name = 'password' and length = '1048') begin /* * alter password column from sysname to nvarchar(524) */ alter table msdb.dbo.MSdistpublishers alter column password nvarchar(524) end /* * convert all the passwords to new encryption */ declare @password nvarchar(524) declare cur_MSdistpublishers CURSOR LOCAL FORWARD_ONLY for select password from msdb.dbo.MSdistpublishers for update of password open cur_MSdistpublishers fetch next from cur_MSdistpublishers into @password while ( @@fetch_status <> -1 ) begin EXEC @retcode = master.dbo.xp_repl_convert_encrypt @password OUTPUT IF @@error <> 0 OR @retcode <> 0 begin rollback transaction return 1 end update msdb.dbo.MSdistpublishers set password=@password where current of cur_MSdistpublishers fetch next from cur_MSdistpublishers into @password end end commit transaction return (0) end go exec dbo.sp_MS_marksystemobject sp_vupgrade_replmsdb go raiserror('Creating procedure sp_restoredbreplication', 0,1) go create procedure sp_restoredbreplication ( @srv_orig sysname, @db_orig sysname ,@keep_replication int = 0 -- Make it int so that we can expand later. ) as /* * used by restore process to strip out replication settings if restoring to non-originating * server/db or system otherwise not capable of keeping replication working * WARNING : procs called here run internal to server and must be owner qualified */ begin set nocount on -- db bits declare @db_tranbit int declare @db_mergbit int declare @db_distbit int select @db_tranbit = 1, @db_mergbit = 4, @db_distbit = 16 declare @repl_installed bit -- repl procs installed flag declare @remove_repl bit -- remove replication flag ; remove on true (1) declare @restoreoverride int declare @db_curr sysname DECLARE @retcode int DECLARE @proc nvarchar(255) -- Fixup lsns for dist db if needed -- This is to make sure that after the restore, the lsns are equal to or larger than -- the ones that have been sent to the publishers before the restore. -- reuse the procedures used by backup. exec @retcode = dbo.sp_MSrepl_backup_start if @retcode <> 0 or @@error <> 0 return 0 exec @retcode = dbo.sp_MSrepl_backup_complete if @retcode <> 0 or @@error <> 0 return 0 -- Support override of replication remove on attach and restore declare @instance sysname declare @regkey nvarchar(260) select @instance = convert(sysname, SERVERPROPERTY('InstanceName')) select @regkey = 'SOFTWARE\Microsoft\' -- default installation if @instance is null SELECT @regkey = @regkey + 'MSSQLServer\Replication' else SELECT @regkey = @regkey + 'Microsoft SQL Server\' + @instance + '\Replication' SELECT @restoreoverride = 0 -- assume normal remove behavior SELECT @proc = 'master.dbo.xp_regread ' EXECUTE @retcode = @proc 'HKEY_LOCAL_MACHINE', @regkey, 'RestoreOverride', @param = @restoreoverride OUTPUT, @no_output = 'no_output' if ( @@error = 0 ) and ( @retcode = 0 ) begin -- ReplRestoreOverride = 1 = user elects to take no cleanup on restore or attach if ( isnull( @restoreoverride, 0 ) = 1 ) return(0) end select @remove_repl = 0, @repl_installed = 1 select @db_curr = db_name() -- check server has replication installed; if not, we cannot remove replication; this should be benign if not exists ( select * from master..MSreplication_options where optname = 'transactional' or optname = 'merge' ) select @repl_installed = 0 -- check restore to same server/db backed up if (( UPPER(@srv_orig) <> UPPER(@@SERVERNAME) ) or ( @db_orig <> @db_curr )) and @keep_replication = 0 select @remove_repl = 1 -- even it is the same server/db, if it is enabled for neither merge nor tran, we will do rmove_repl. -- if not exists (select * from master..sysdatabases where name = @db_curr collate database_default and category & @db_tranbit = @db_tranbit ) -- and not exists (select * from master..sysdatabases where name = @db_curr collate database_default and category & @db_mergbit = @db_mergbit ) -- select @remove_repl = 1 -- in order to comply with BOL on restoring subscriber databases, this code segment has to go. -- upgrade repl schema to latest version if it is restore of earlier database version (e.g. SQL70 backup) if ( exists( select * from sysobjects where name = N'syspublications' ) -- we think this is a tran pub db and not exists ( select * from sysobjects where name = N'sysextendedarticlesview' ) ) or ( exists( select * from sysobjects where name = N'sysmergepublications' ) -- we think this is a merge pub db and not exists ( select * from sysobjects where name = N'sysmergeextendedarticlesview' ) ) begin exec dbo.sp_vupgrade_publisherdb @ver_old = 999, @ver_retention = 999 -- retention and old version not relevant on restore -- update subscription tables schema only -- skip any recompile of procs, views, etc. -- we will just drop them after restore exec dbo.sp_vupgrade_MSsubscription_properties exec dbo.sp_vupgrade_subscription_tables exec dbo.sp_vupgrade_mergetables @skip_procgen = 1 end -- subscribing dbs are assumed ok -- distribution dbs are assumed ok -- publishing db check : transactional : requires coordinated restore of dist db - no way to check if ( exists( select * from sysobjects where name = 'syspublications' ) -- exists( select * from syspublications ) and not exists( select * from master..sysdatabases where name = @db_curr collate database_default and category & @db_tranbit = @db_tranbit ) ) begin -- publications exist in db, but db on server is not published; -- unpublish the db, ignoring distributor cleanup update master.dbo.sysdatabases set category = category | @db_tranbit where name = @db_curr collate database_default exec dbo.sp_MSpublishdb 'false', 1 update master.dbo.sysdatabases set category = category & ~@db_tranbit where name = @db_curr collate database_default -- we've already brute force stripped replication from the db, -- don't call sp_removedbreplication at proc exit end if ( @repl_installed = 1 ) and ( @remove_repl = 1 ) exec dbo.sp_removedbreplication @db_curr end go exec dbo.sp_MS_marksystemobject sp_restoredbreplication go -- -- Name: sp_MSget_publisher_rpc -- -- Description: This proc is invoked on subscriber by synctran trigger -- for retrieving publisher RPC connection information during -- immediate updating operation. -- -- Parameter: Refer to the comments in the create procedure statement -- -- Returns: 1 or 0 0 = success -- -- Security: Public procedure - Internal security check. -- raiserror('Creating procedure sp_MSget_publisher_rpc', 0,1) GO CREATE PROCEDURE sp_MSget_publisher_rpc ( @trigger_id int ,@connect_string nvarchar(2000) output ,@owner sysname = null ) AS begin SET NOCOUNT ON declare @publisher sysname ,@publisher_db sysname ,@login sysname ,@password nvarchar(524) ,@security_mode int ,@object_id int ,@retcode int -- -- Security check -- Make sure this proc is infact being called from the given object(trigger) -- if trigger_nestlevel(@trigger_id) = 0 begin raiserror(14126, 16, 4) return (1) -- current user does not have insert permission to underlying table end -- -- Security check: the caller of this SP has to be one of the -- predefined replication triggers defined in the db -- if (@owner is null) begin if (@trigger_id not in (select object_id(object_name) from dbo.MSreplication_objects where object_type = 'T')) begin raiserror(14126, 16, 4) return -1 end end else begin if (@trigger_id not in (select object_id(quotename(@owner) + N'.' + quotename(object_name)) from dbo.MSreplication_objects where object_type = 'T')) begin raiserror(14126, 16, 4) return -1 end end -- -- Get security from property table, if nothing find, the rpc will fail. -- IF EXISTS (select * from dbo.sysobjects where name = 'MSsubscription_properties' and type = 'U') begin select @login = publisher_login, @password = publisher_password, @security_mode = publisher_security_mode, @publisher = o.publisher, @publisher_db = o.publisher_db from (dbo.MSsubscription_properties p join dbo.MSreplication_objects o on UPPER(p.publisher) = UPPER(o.publisher) and p.publisher_db = o.publisher_db and p.publication = o.publication) where o.object_name = object_name(@trigger_id) exec @retcode = master.dbo.xp_repl_help_connect @password OUTPUT if @@error <> 0 OR @retcode <> 0 return 1 end else begin -- RPC security info invalid raiserror(21079, 16, -1) return(1) end -- -- prepare the connect string now -- if @security_mode = 2 -- 2 = use sysservers begin select @connect_string = null end else begin if @login is null begin -- RPC security info invalid raiserror(21079, 16, -1) return(1) end if @password is null select @password = N'' -- Names containing space in connection string is automatically enabled. -- [] and ' are not recoginized by opendatasource -- Note ';' in names in connection string will mess things up. select @connect_string = 'SERVER=' + @publisher + ';UID=' + @login + ';PWD=' + @password + ';' end end GO exec dbo.sp_MS_marksystemobject sp_MSget_publisher_rpc go raiserror('Creating procedure sp_link_publication', 0,1) GO CREATE PROCEDURE sp_link_publication ( @publisher sysname, -- publishing server name @publisher_db sysname, -- publishing database name. If NULL then same as current db @publication sysname, -- publication name @security_mode int, -- 0 = standard; 2 = static linked server entry @login sysname = NULL, @password sysname = NULL, @distributor sysname = NULL ) AS BEGIN set nocount on declare @retcode int declare @enc_password nvarchar(524) -- Security Check EXEC @retcode = dbo.sp_MSreplcheck_subscribe IF @@ERROR <> 0 or @retcode <> 0 RETURN(1) -- Parameter check: @security_mode if @security_mode <> 0 and @security_mode <> 2 begin RAISERROR(21055, 16, -1, '@security_mode','sp_link_publication') RETURN (1) end if @security_mode = 2 and not exists (select * from master..sysservers where UPPER(srvname) = UPPER(@publisher) collate database_default) begin RAISERROR(20620, 16, -1, @publisher) RETURN (1) end IF @password = N'' select @password = NULL /* ** Check to see if MSsubscription_properties table exists. ** If not, create it. */ exec @retcode = dbo.sp_MScreate_sub_tables IF @@ERROR <> 0 or @retcode <> 0 return 1 -- Encrypt the password set @enc_password = @password EXEC @retcode = master.dbo.xp_repl_encrypt @enc_password OUTPUT IF @@error <> 0 OR @retcode <> 0 return 1 IF NOT EXISTS (select * from MSsubscription_properties where UPPER(publisher) = UPPER(@publisher) and publisher_db = @publisher_db and publication = @publication) BEGIN INSERT INTO MSsubscription_properties (publisher, publisher_db, publication, publication_type, publisher_login,publisher_password, publisher_security_mode, distributor, distributor_login, distributor_password, distributor_security_mode) values (@publisher, @publisher_db, @publication, 0, @login, @enc_password, @security_mode, @distributor, NULL, NULL, 1) END ELSE BEGIN update MSsubscription_properties set publisher_login = @login, publisher_password = @enc_password, publisher_security_mode = @security_mode, distributor = isnull(@distributor, distributor) where UPPER(publisher) = UPPER(@publisher) and publisher_db = @publisher_db and publication = @publication END END go exec dbo.sp_MS_marksystemobject sp_link_publication go -- This proc is invoked on subscriber. -- internal routine - not granted to public raiserror('Creating procedure sp_MSreset_queue', 0,1) GO CREATE PROCEDURE sp_MSreset_queue ( @publisher sysname, -- publishing server name @publisher_db sysname, -- publishing database name. @publication sysname, -- publication name, @artid int) as begin declare @subserver sysname ,@subdbname sysname ,@queue_id sysname ,@update_mode int ,@retcode smallint ,@vbartid varbinary(20) ,@queue_server sysname set nocount on select @subserver = @@servername, @subdbname = db_name(), @update_mode = update_mode, @queue_id = queue_id, @queue_server = queue_server from MSsubscription_agents where UPPER(publisher) = UPPER(@publisher) and publisher_db = @publisher_db and publication = @publication if (@update_mode in (2,3)) begin -- -- MSMQ processing -- prefix the queue_id with queue server in direct format -- and then perform the queue reset -- select @queue_id = N'DIRECT=OS:' + @queue_server + N'\PRIVATE$\' + @queue_id begin distributed tran exec @retcode = master.dbo.xp_resetqueue @queue_id, @subserver, @subdbname, @publication, @artid if (@retcode != 0 or @@error != 0) begin if (@@trancount > 0) rollback tran return (1) end end else if (@update_mode in (4,5)) begin declare @tranid sysname begin tran -- -- process MSreplication_queue -- select @retcode = 0 if (exists (select * from sysobjects where name = 'MSreplication_queue')) begin -- -- Strictly speaking we do no need -- to delete but, makes it easy for -- the queue reader agent -- Do not delete any reset messages -- delete dbo.MSreplication_queue where publisher = UPPER(@publisher) and publisher_db = @publisher_db and publication = @publication and tranid not like N'sub-reset%' end else begin -- -- first queue subscription is being initialized -- create queue if necessary -- exec @retcode = sp_MScreate_sub_tables @tran_sub_table = 0, @property_table = 0, @sqlqueue_table = 1 end if (@retcode != 0 or @@error != 0) begin if (@@trancount > 0) rollback tran return (1) end -- -- process MSrepl_queuedtraninfo -- if (exists (select * from sysobjects where name = 'MSrepl_queuedtraninfo')) begin -- -- Strictly speaking we do no need -- to delete but, makes it easy for -- the queue reader agent -- Do not delete any reset messages -- delete dbo.MSrepl_queuedtraninfo where publisher = UPPER(@publisher) and publisher_db = @publisher_db and publication = @publication and tranid not like N'sub-reset%' end else begin -- -- first queue subscription is being initialized -- create the traninfo if necessary -- exec @retcode = sp_MScreate_sub_tables @tran_sub_table = 0, @property_table = 0, @sqlqueue_table = 1 end if (@retcode != 0 or @@error != 0) begin if (@@trancount > 0) rollback tran return (1) end -- -- for subscription reinitialization we -- need to insert a RESYNC command message -- select @vbartid = cast(@artid as varbinary(20)) ,@tranid = N'sub-reset-' + cast(NEWID() as sysname) insert into dbo.MSreplication_queue (publisher, publisher_db, publication,tranid, commandtype, data, datalen) values (UPPER(@publisher), @publisher_db, @publication, @tranid, 2, @vbartid, datalength(@vbartid)) if ((@@error != 0) or (@retcode != 0)) begin if (@@trancount > 0) rollback tran return (1) end -- -- add an entry in MSrepl_queuedtraninfo -- insert into dbo.MSrepl_queuedtraninfo (publisher,publisher_db,publication,tranid,maxorderkey,commandcount) values (UPPER(@publisher),@publisher_db,@publication,@tranid,@@identity,1) end commit tran return 0 end GO exec dbo.sp_MS_marksystemobject sp_MSreset_queue go -- -- Name: sp_MSreset_queued_reinit -- -- Description: This proc is invoked on publisher, for resetting -- the queued_reinit flag for a given subscription -- -- Parameter: Refer to the comments in the create procedure statement -- -- Returns: 1 or 0 0 = success -- -- Security: Public procedure - does PAL security check. -- raiserror('Creating procedure sp_MSreset_queued_reinit', 0,1) GO create procedure sp_MSreset_queued_reinit ( @subscriber sysname, -- subscriber server name @subscriber_db sysname, -- subscribing database name. @artid int) -- article id as begin set nocount on declare @srvid int ,@retcode int ,@publication sysname -- -- PAL security check -- Get publication name using artid -- select @publication = p.name from syspublications p join sysarticles a on p.pubid = a.pubid where a.artid = @artid if (@publication is null) begin return 1 end exec @retcode = dbo.sp_MSreplcheck_pull @publication = @publication if @@error <> 0 or @retcode <> 0 begin return (1) end select @srvid = srvid from master.dbo.sysservers where UPPER(srvname) = UPPER(@subscriber) collate database_default -- -- set the reinit flag -- update dbo.syssubscriptions set queued_reinit = 0 where artid = @artid and srvid = @srvid and dest_db = @subscriber_db if (@@error != 0) return 1 -- all done return 0 end GO exec dbo.sp_MS_marksystemobject sp_MSreset_queued_reinit go grant execute on dbo.sp_MSreset_queued_reinit to public go raiserror('Creating procedure sp_MSinit_subscription_agent', 0,1) GO -- This proc is called by distribution agent. CREATE PROCEDURE sp_MSinit_subscription_agent @publisher sysname, -- publishing server name @publisher_db sysname, -- publishing database name. If NULL then same as current db @publication sysname, -- publication name, @subscription_type int AS set nocount on declare @retcode int declare @login_time datetime -- Security Check EXEC @retcode = dbo.sp_MSreplcheck_subscribe IF @@ERROR <> 0 or @retcode <> 0 RETURN(1) -- For non independent agent publications if @publication is null or @publication = '' set @publication = 'ALL' select @login_time = login_time from master..sysprocesses where spid = @@spid if not exists (select * from MSsubscription_agents where UPPER(publisher) = UPPER(@publisher) and publisher_db = @publisher_db and publication = @publication and subscription_type = @subscription_type) begin INSERT INTO MSsubscription_agents (publisher, publisher_db, publication, subscription_type, queue_id, update_mode, failover_mode, spid, login_time ) values (@publisher, @publisher_db, @publication, @subscription_type, null, 1, 0, @@spid, @login_time) end else begin -- It is possible that 2 instance of the distribution agent do this update at -- the same time. One will fail later at the instance check at the distributor -- side. We no longer use the spid and login_time column anywhere else. update MSsubscription_agents set spid = @@spid, login_time = @login_time where UPPER(publisher) = UPPER(@publisher) and publisher_db = @publisher_db and publication = @publication and subscription_type = @subscription_type end go exec dbo.sp_MS_marksystemobject sp_MSinit_subscription_agent go grant execute on dbo.sp_MSinit_subscription_agent to public go raiserror('Creating procedure sp_MSupdatelastsyncinfo', 0,1) GO -- This proc is called by distribution agent. CREATE PROCEDURE sp_MSupdatelastsyncinfo @publisher sysname, -- publishing server name @publisher_db sysname, -- publishing database name. If NULL then same as current db @publication sysname, -- publication name, @subscription_type int, @last_sync_status int, @last_sync_summary sysname AS set nocount on declare @retcode int -- Security Check EXEC @retcode = dbo.sp_MSreplcheck_subscribe IF @@ERROR <> 0 or @retcode <> 0 RETURN(1) if object_id('dbo.MSsubscription_agents') is null return(1) -- For non independent agent publications if @publication is null or @publication = '' set @publication = 'ALL' if not exists (select * from MSsubscription_agents where UPPER(publisher) = UPPER(@publisher) and publisher_db = @publisher_db and publication = @publication and subscription_type = @subscription_type) begin exec dbo.sp_MSinit_subscription_agent @publisher, @publisher_db, @publication, @subscription_type end update MSsubscription_agents set last_sync_time = getdate(), last_sync_status = @last_sync_status, last_sync_summary = @last_sync_summary where UPPER(publisher) = UPPER(@publisher) and publisher_db = @publisher_db and publication = @publication and subscription_type = @subscription_type update MSreplication_subscriptions set time = convert(smalldatetime, getdate()) WHERE UPPER(publisher) = UPPER(@publisher) AND publisher_db = @publisher_db AND ((@publication = N'ALL' and independent_agent = 0) or @publication = publication) and subscription_type = @subscription_type go exec dbo.sp_MS_marksystemobject sp_MSupdatelastsyncinfo go grant execute on dbo.sp_MSupdatelastsyncinfo to public go raiserror('Creating procedure sp_MSget_attach_state', 0,1) GO -- This proc is called by distribution agent. CREATE PROCEDURE sp_MSget_attach_state @publisher sysname, -- publishing server name @publisher_db sysname, -- publishing database name. If NULL then same as current db @publication sysname, -- publication name, @subscription_type int AS set nocount on declare @retcode int -- Security Check -- We only run on subscriber so we only need sysadmin and dbo exec @retcode = dbo.sp_MSreplcheck_publish if @@error <> 0 or @retcode <> 0 begin return (1) end -- For non independent agent publications if @publication is null or @publication = '' set @publication = 'ALL' select attach_state, attach_version from MSsubscription_agents where UPPER(publisher) = UPPER(@publisher) and publisher_db = @publisher_db and publication = @publication and subscription_type = @subscription_type go exec dbo.sp_MS_marksystemobject sp_MSget_attach_state go grant execute on dbo.sp_MSget_attach_state to public go raiserror('Creating procedure sp_MSreset_attach_state', 0,1) GO -- This proc is called by distribution agent. CREATE PROCEDURE sp_MSreset_attach_state ( @publisher sysname, -- publishing server name @publisher_db sysname, -- publishing database name. If NULL then same as current db @publication sysname, -- publication name, @subscription_type int ) AS BEGIN set nocount on declare @retcode int -- Security Check EXEC @retcode = dbo.sp_MSreplcheck_subscribe IF @@ERROR <> 0 or @retcode <> 0 RETURN(1) -- For non independent agent publications if @publication is null or @publication = '' select @publication = 'ALL' -- -- For Queued updating subscriptions, (re)initialize -- the queue -- if exists (select * from dbo.MSsubscription_agents where UPPER(publisher) = UPPER(@publisher) and publisher_db = @publisher_db and publication = @publication and subscription_type = @subscription_type and update_mode in (2,3,4,5)) begin declare @artid int -- -- for each article in this subscription -- declare #hc_article CURSOR LOCAL FORWARD_ONLY for select artid from dbo.MSsubscription_articles as art join dbo.MSsubscription_agents as agent on art.agent_id = agent.id where UPPER(agent.publisher) = UPPER(@publisher) and agent.publisher_db = @publisher_db and agent.publication = @publication and agent.subscription_type = @subscription_type open #hc_article fetch #hc_article into @artid while (@@fetch_status = 0) begin -- -- we cannot have an NULL article id -- if (@artid IS NULL) begin raiserror('sp_MSreset_attach_state(debug) - queued article id cannot be NULL', 16, 1) return (1) end -- -- reset the queue -- exec @retcode = dbo.sp_MSreset_queue @publisher, @publisher_db, @publication, @artid IF (@retcode != 0 or @@ERROR != 0) begin raiserror('sp_MSreset_attach_state(debug) - sp_MSreset_queue failed', 16, 2) return (1) end -- -- fetch next article -- fetch #hc_article into @artid end close #hc_article deallocate #hc_article end update MSsubscription_agents set attach_state = 0 where UPPER(publisher) = UPPER(@publisher) and publisher_db = @publisher_db and publication = @publication and subscription_type = @subscription_type END go exec dbo.sp_MS_marksystemobject sp_MSreset_attach_state go grant execute on dbo.sp_MSreset_attach_state to public go -- -- Name: sp_MSset_subscription_properties -- -- Description: This procedure is called by distribution agent to set the -- subscription metadata during subscription initialization. Invoked on subscribing -- database on subscriber. -- -- Parameter: Refer to the comments in the create procedure statement -- -- Returns: 1 or 0 0 = success -- -- Security: Public procedure - internal security check. -- raiserror('Creating procedure sp_MSset_subscription_properties', 0,1) GO CREATE PROCEDURE sp_MSset_subscription_properties ( @publisher sysname, -- publishing server name @publisher_db sysname, -- publishing database name. If NULL then same as current db @publication sysname, -- publication name, @subscription_type int, @allow_subscription_copy bit, @queue_id sysname, @update_mode int, @attach_version binary(16), @queue_server sysname = NULL ) AS BEGIN set nocount on declare @retcode int -- Security Check EXEC @retcode = dbo.sp_MSreplcheck_subscribe IF @@ERROR <> 0 or @retcode <> 0 RETURN(1) -- For non independent agent publications if @publication is null or @publication = '' set @publication = 'ALL' if @queue_server = N'' select @queue_server = NULL if @queue_id = N'' select @queue_id = NULL -- -- Update metadata in MSsubscription_agents -- update dbo.MSsubscription_agents set allow_subscription_copy = @allow_subscription_copy, update_mode = @update_mode, queue_id = @queue_id, queue_server = @queue_server, attach_version = @attach_version where UPPER(publisher) = UPPER(@publisher) and publisher_db = @publisher_db and publication = @publication and subscription_type = @subscription_type -- -- for queued pull subscriptions -- update column update_mode in MSreplication_subscriptions -- as we never know the right update_mode until initialization -- if ((@subscription_type = 1) and (@queue_id IS NOT NULL) and exists (select * from MSreplication_subscriptions WHERE UPPER(publisher) = UPPER(@publisher) AND publisher_db = @publisher_db AND publication = @publication AND subscription_type = @subscription_type)) begin update MSreplication_subscriptions set update_mode = @update_mode WHERE UPPER(publisher) = UPPER(@publisher) AND publisher_db = @publisher_db AND publication = @publication AND subscription_type = @subscription_type end END go exec dbo.sp_MS_marksystemobject sp_MSset_subscription_properties go grant execute on dbo.sp_MSset_subscription_properties to public go -- -- Name: sp_MSset_sub_guid -- -- Description: This procedure is called by distribution agent to set the -- subscription metadata during subscription attach. Invoked on subscribing -- database on subscriber. -- -- Parameter: Refer to the comments in the create procedure statement -- -- Returns: 1 or 0 0 = success -- -- Security: Public procedure - internal security check. -- raiserror('Creating procedure sp_MSset_sub_guid', 0,1) GO CREATE PROCEDURE sp_MSset_sub_guid ( @publisher sysname, -- publishing server name @publisher_db sysname, -- publishing database name. If NULL then same as current db @publication sysname, -- publication name, @subscription_type int, @subscription_guid binary(16), @queue_id sysname, @queue_server sysname = NULL ) AS BEGIN set nocount on declare @retcode int ,@independent_agent bit ,@subqueue_id sysname -- Security Check EXEC @retcode = dbo.sp_MSreplcheck_subscribe IF @@ERROR <> 0 or @retcode <> 0 RETURN(1) -- For non independent agent publications if @publication is null or @publication = '' begin select @publication = 'ALL' ,@independent_agent = 0 end else select @independent_agent = 1 if @queue_id = N'' select @queue_id = NULL if @queue_server = N'' select @queue_server = NULL -- -- Special processing when we are dealing with pull SQL queue updating subscription -- if ((@subscription_type = 1) and substring(@queue_id, 1, 10) = N'mssqlqueue') begin -- -- For SQL Queue case - Check the current queue_id on the table -- select @subqueue_id = queue_id from dbo.MSsubscription_agents where UPPER(publisher) = UPPER(@publisher) and publisher_db = @publisher_db and publication = @publication and subscription_type = @subscription_type if (@subqueue_id is not NULL and substring(@subqueue_id, 1, 10) = N'mssqlqueue') begin -- -- Use the local Queue ID on subscriber as this contains the queue version. -- We are attaching an initialized subscription and do not want to change the -- queue version stored in queue_id for SQL Queues. The value passed by Distribution -- Agent is from the distributor metadata and does not contain the queue version information. -- This is specific to SQL Queues only. -- select @queue_id = @subqueue_id end end -- -- Update metadata in MSsubscription_agents -- update MSsubscription_agents set queue_id = @queue_id ,queue_server = @queue_server where UPPER(publisher) = UPPER(@publisher) and publisher_db = @publisher_db and publication = @publication and subscription_type = @subscription_type update MSreplication_subscriptions set [time] = getdate(), subscription_guid = @subscription_guid where UPPER(publisher) = UPPER(@publisher) and publisher_db = @publisher_db and (@independent_agent = 0 or publication = @publication) and subscription_type = @subscription_type and independent_agent = @independent_agent END go exec dbo.sp_MS_marksystemobject sp_MSset_sub_guid go grant execute on dbo.sp_MSset_sub_guid to public go -- -- sp_populateqtraninfo -- -- Owner: KaushikC -- -- Description: this stored procedure populates table -- MSrepl_queuedtraninfo based on the existing data -- in MSreplication_queue. It is used during the -- upgrade process when MSrepl_queuedtraninfo is -- created. Executed on subscriber database. -- -- Parameters: -- as defined in the create proc statement -- -- Results: -- None -- -- Returns: -- 0 if success -- 1 if failure -- -- Security: internal helper procedure - not granted to public -- raiserror('Creating procedure sp_populateqtraninfo', 0,1) GO CREATE PROCEDURE sp_populateqtraninfo as begin -- -- initiate local transaction -- begin tran sp_populateqtraninfo save tran sp_populateqtraninfo -- -- see if we need to populate -- if EXISTS (SELECT * FROM dbo.MSreplication_queue) begin -- -- There is data in queue -- Populate MSrepl_queuedtraninfo based on what is there -- declare @publisher sysname ,@publisherdb sysname ,@publication sysname ,@tranid sysname ,@orderkey bigint ,@commandcount bigint declare #htctranseq cursor local for select publisher, publisher_db, publication, tranid, orderkey from dbo.MSreplication_queue with (READPAST) order by orderkey asc open #htctranseq fetch #htctranseq into @publisher, @publisherdb, @publication, @tranid, @orderkey IF @@ERROR <> 0 goto cleanup while (@@fetch_status != -1) begin -- -- update/insert entry in MSrepl_queuedtraninfo for this transaction -- if exists (select * from dbo.MSrepl_queuedtraninfo where publisher = UPPER(@publisher) and publisher_db = @publisherdb and publication = @publication and tranid = @tranid) begin -- -- row for this transaction exists - update it -- update dbo.MSrepl_queuedtraninfo set maxorderkey = @orderkey ,commandcount = commandcount + 1 where publisher = UPPER(@publisher) and publisher_db = @publisherdb and publication = @publication and tranid = @tranid end else begin -- -- row for this transaction does not exist - insert it -- insert into dbo.MSrepl_queuedtraninfo (publisher,publisher_db,publication,tranid,maxorderkey,commandcount) values (UPPER(@publisher),@publisherdb,@publication,@tranid,@orderkey,1) end IF @@ERROR <> 0 goto cleanup -- -- get the next row -- fetch #htctranseq into @publisher, @publisherdb, @publication, @tranid, @orderkey end close #htctranseq deallocate #htctranseq end -- -- commit local transaction -- commit tran sp_populateqtraninfo -- -- all done -- return 0 cleanup: -- -- error cleanup -- rollback local tran -- rollback tran sp_populateqtraninfo commit tran return 1 end go exec dbo.sp_MS_marksystemobject sp_populateqtraninfo go raiserror('Creating procedure sp_MScreate_sub_tables', 0,1) GO CREATE PROCEDURE sp_MScreate_sub_tables ( @tran_sub_table bit = 0, @property_table bit = 1, @sqlqueue_table bit = 0 ) as BEGIN set nocount on declare @retcode int IF @tran_sub_table = 1 and (NOT EXISTS (SELECT * FROM sysobjects WHERE type = 'U' AND name = 'MSreplication_subscriptions')) BEGIN CREATE TABLE dbo.MSreplication_subscriptions ( publisher sysname NOT NULL, publisher_db sysname NOT NULL, publication sysname NULL, independent_agent bit NOT NULL, subscription_type int NOT NULL, distribution_agent sysname NULL, time smalldatetime NOT NULL, description nvarchar(255) NULL, transaction_timestamp varbinary(16) NOT NULL, -- SyncTran update_mode tinyint NOT NULL, agent_id binary(16) NULL, subscription_guid binary(16) NULL, subid binary(16) NULL, immediate_sync bit NOT NULL default 1 -- sync_mode with a default of 1 ) IF @@ERROR <> 0 GOTO UNDO CREATE UNIQUE CLUSTERED INDEX uc1MSReplication_subscriptions ON MSreplication_subscriptions(publication, publisher_db, publisher, subscription_type) IF @@ERROR <> 0 GOTO UNDO EXEC dbo.sp_MS_marksystemobject 'MSreplication_subscriptions' IF @@ERROR <> 0 GOTO UNDO END IF @tran_sub_table = 1 BEGIN IF NOT EXISTS (SELECT * FROM sysobjects WHERE type = 'U' AND name = 'MSsubscription_agents') BEGIN CREATE TABLE dbo.MSsubscription_agents ( id int identity, publisher sysname NOT NULL, publisher_db sysname NOT NULL, publication sysname NOT NULL, subscription_type int NOT NULL, queue_id sysname NULL, update_mode tinyint default 0 not null, -- 0 = read only, 1 = sync/immediate, 2 = queued, 3 = failover, 4 = sqlqueued, 5 = sqlqueued failover failover_mode bit default 0 not null, -- 0 - sync/immediate, 1 = queued spid int NOT NULL, login_time datetime NOT NULL, allow_subscription_copy bit default 0 not null, attach_state int default 0 not null, -- 0: not attached 1 attached but not processed 2 attached and processed. attach_version binary(16) default newid() not null, last_sync_status int NULL, -- allow null for upgrade last_sync_summary sysname NULL, -- allow null for upgrade last_sync_time datetime NULL, -- allow null for upgrade queue_server sysname NULL -- only used for MSMQ based updating subscribers ) IF @@ERROR <> 0 GOTO UNDO CREATE unique CLUSTERED INDEX ucMSsubscription_agents ON dbo.MSsubscription_agents (publication, publisher_db, publisher, subscription_type) CREATE INDEX ucMSsubscription_agents_id ON dbo.MSsubscription_agents (id) EXEC dbo.sp_MS_marksystemobject 'MSsubscription_agents' IF @@ERROR <> 0 GOTO UNDO grant select on dbo.MSsubscription_agents to public IF @@ERROR <> 0 GOTO UNDO END ELSE BEGIN -- -- table exists - add new columns -- if not exists (select * from dbo.syscolumns where id = object_id('MSsubscription_agents') and name = 'queue_server') begin alter table dbo.MSsubscription_agents add queue_server sysname NULL exec dbo.sp_MSupdate_mqserver_subdb end END END IF @property_table = 1 and NOT EXISTS (SELECT * FROM sysobjects WHERE type = 'U' AND name = 'MSsubscription_properties') BEGIN BEGIN TRAN CREATE TABLE dbo.MSsubscription_properties ( publisher sysname NOT NULL, publisher_db sysname NOT NULL, publication sysname NOT NULL, publication_type int NOT NULL, publisher_login sysname NULL, publisher_password nvarchar(524) NULL, publisher_security_mode int NOT NULL, distributor sysname NULL, distributor_login sysname NULL, distributor_password nvarchar(524) NULL, distributor_security_mode int NOT NULL, ftp_address sysname NULL, ftp_port int NULL, ftp_login sysname NULL, ftp_password nvarchar(524) NULL, alt_snapshot_folder nvarchar(255) NULL, working_directory nvarchar(255) NULL, use_ftp bit default 0 NOT NULL, dts_package_name sysname NULL, dts_package_password nvarchar(524) NULL, -- default to be at the subscriber dts_package_location int default 1 NOT NULL, enabled_for_syncmgr bit default 0 NOT NULL, offload_agent bit default 0 NOT NULL, offload_server sysname NULL, dynamic_snapshot_location nvarchar(255) NULL ) IF @@ERROR <> 0 GOTO UNDO CREATE UNIQUE CLUSTERED INDEX uc1MSsubscription_properties ON MSsubscription_properties(publication, publisher_db, publisher) IF @@ERROR <> 0 GOTO UNDO EXEC @retcode = dbo.sp_MS_marksystemobject 'MSsubscription_properties' if @retcode <> 0 or @@error <> 0 GOTO UNDO COMMIT TRAN END IF @sqlqueue_table = 1 BEGIN declare @folddata bit BEGIN TRAN if EXISTS (SELECT * FROM dbo.sysobjects WHERE type = 'U' AND name = 'MSreplication_queue') BEGIN -- -- table exists - check if we need to add columns -- if not exists (select * from dbo.syscolumns where id = object_id('MSreplication_queue') and name = 'cmdstate') BEGIN ALTER TABLE dbo.MSreplication_queue ADD cmdstate bit DEFAULT 0 NOT NULL IF @@ERROR <> 0 GOTO UNDO END -- -- change data column from text to varbinary(8000) -- SPECIAL CASE : since a simple ALTER does not work here -- we create a temp table to save the existing data and then -- recreate the table -- if exists (select * from dbo.syscolumns where id = object_id('MSreplication_queue') and name = 'data' and xtype = 34) begin -- -- save existing column data -- if exists (select * from dbo.MSreplication_queue) begin select @folddata = 1 create table #olddata ( publisher sysname collate database_default not null , publisher_db sysname collate database_default not null , publication sysname collate database_default not null , tranid sysname collate database_default not null , data varbinary(8000) NULL , datalen int, commandtype int, insertdate datetime , orderkey bigint, cmdstate bit) insert into #olddata select publisher, publisher_db, publication, tranid, CAST(data as varbinary(8000)), datalen, commandtype, insertdate, orderkey, cmdstate from dbo.MSreplication_queue if @@error != 0 goto UNDO end -- -- drop table -- DROP TABLE dbo.MSreplication_queue IF @@ERROR <> 0 GOTO UNDO end END -- -- Create table if it does not exist -- if NOT EXISTS (SELECT * FROM dbo.sysobjects WHERE type = 'U' AND name = 'MSreplication_queue') BEGIN CREATE TABLE dbo.MSreplication_queue ( publisher sysname NOT NULL , publisher_db sysname NOT NULL , publication sysname NOT NULL , tranid sysname NOT NULL , data varbinary(8000) NULL , datalen int DEFAULT 0 , commandtype int NULL , insertdate datetime DEFAULT GETDATE(), orderkey bigint IDENTITY(1,1) PRIMARY KEY, cmdstate bit DEFAULT 0 NOT NULL ) IF @@ERROR <> 0 GOTO UNDO /**** CREATE NONCLUSTERED INDEX nc1MSreplication_queue ON MSreplication_queue(tranid) IF @@ERROR <> 0 GOTO UNDO ****/ EXEC @retcode = dbo.sp_MS_marksystemobject 'MSreplication_queue' if @retcode <> 0 or @@error <> 0 GOTO UNDO -- -- Do we need to restore old data -- if (@folddata = 1) begin insert dbo.MSreplication_queue (publisher, publisher_db, publication, tranid, data, datalen, commandtype, insertdate, cmdstate) select publisher, publisher_db, publication, tranid, data, datalen, commandtype, insertdate, cmdstate from #olddata order by orderkey if @@error != 0 goto UNDO drop table #olddata if @@error != 0 goto UNDO end END -- -- Table MSrepl_queuedtraninfo -- Create table if it does not exist -- if NOT EXISTS (SELECT * FROM dbo.sysobjects WHERE type = 'U' AND name = 'MSrepl_queuedtraninfo') BEGIN CREATE TABLE dbo.MSrepl_queuedtraninfo ( publisher sysname NOT NULL , publisher_db sysname NOT NULL , publication sysname NOT NULL , tranid sysname NOT NULL , maxorderkey bigint NOT NULL, commandcount bigint NOT NULL ) IF @@ERROR <> 0 GOTO UNDO CREATE CLUSTERED INDEX nc1MSrepl_queuedtraninfo ON MSrepl_queuedtraninfo(publisher,publisher_db,publication,tranid) IF @@ERROR <> 0 GOTO UNDO EXEC @retcode = dbo.sp_MS_marksystemobject 'MSrepl_queuedtraninfo' if @retcode <> 0 or @@error <> 0 GOTO UNDO -- -- Populate this table as necessary -- exec @retcode = dbo.sp_populateqtraninfo if @retcode <> 0 or @@error <> 0 GOTO UNDO END COMMIT TRAN END return(0) UNDO: IF @@TRANCOUNT = 1 ROLLBACK TRAN ELSE COMMIT TRAN return(1) END go exec dbo.sp_MS_marksystemobject sp_MScreate_sub_tables go -- -- sp_MSupdate_mqserver_subdb -- -- This procedure is called to upgrade the MSMQ related entries in -- MSsubscription_agents in subscription database - this processing -- cannot be done directly inside sp_MScreate_sub_tables since we need the -- queue_server column for the processing and we can get a syntax error -- if the table exists without the column -- -- Assumption : MSsubscription_agents has been created -- and column queue_server exists -- raiserror('Creating procedure sp_MSupdate_mqserver_subdb', 0,1) GO create procedure sp_MSupdate_mqserver_subdb as begin if exists (select * from dbo.MSsubscription_agents where queue_id IS NOT NULL and substring(queue_id, 1, 10) != N'mssqlqueue' and queue_server IS NULL) begin -- -- we have entries for active Queued subscriptions using MSMQ that need upgrade -- declare @queue_server sysname ,@publisher sysname ,@publisher_db sysname ,@publication sysname DECLARE hC CURSOR LOCAL FAST_FORWARD FOR select publisher, publisher_db, publication from dbo.MSsubscription_agents where queue_id IS NOT NULL and substring(queue_id, 1, 10) != N'mssqlqueue' and queue_server IS NULL OPEN hC FETCH hC INTO @publisher, @publisher_db, @publication WHILE (@@fetch_status != -1) BEGIN -- -- the table MSsubscription_properties has to exist; -- prepare the queue server name from distributor name -- strip the instance name if necessary -- select @queue_server = ISNULL(distributor, @@servername) from dbo.MSsubscription_properties where UPPER(publisher) = UPPER(@publisher) and publisher_db = @publisher_db and publication = @publication if (charindex(N'\', @queue_server) > 0) select @queue_server = substring(@queue_server, 1, charindex(N'\', @queue_server) - 1) -- -- set the queue_server for this entry -- update dbo.MSsubscription_agents set queue_server = @queue_server where UPPER(publisher) = UPPER(@publisher) and publisher_db = @publisher_db and publication = @publication -- -- get next entry -- FETCH hC INTO @publisher, @publisher_db, @publication END CLOSE hC DEALLOCATE hC end end go exec dbo.sp_MS_marksystemobject sp_MSupdate_mqserver_subdb go raiserror('Creating procedure sp_MS_replication_installed', 0,1) GO CREATE PROCEDURE sp_MS_replication_installed as set nocount on declare @isinstalled int select @isinstalled = 0 create table #keyvalues (keyvalue nvarchar(255) collate database_default not null, keyvaluedata nvarchar(255) collate database_default null) declare @instance sysname declare @regkey nvarchar(260) select @instance = convert(sysname, SERVERPROPERTY('InstanceName')) select @regkey = 'SOFTWARE\Microsoft\' -- default installation if @instance is null SELECT @regkey = @regkey + 'MSSQLServer\Replication' else SELECT @regkey = @regkey + 'Microsoft SQL Server\' + @instance + '\Replication' insert into #keyvalues exec master..xp_regenumvalues 'HKEY_LOCAL_MACHINE', @regkey if @@ERROR <> 0 begin drop table #keyvalues return (-1) end select @isinstalled = convert (int, (select keyvaluedata from #keyvalues where keyvalue = N'IsInstalled')) drop table #keyvalues if (@isinstalled is null or @isinstalled = 0) begin raiserror (21028, 16, -1) return (0) end return (1) go exec dbo.sp_MS_marksystemobject sp_MS_replication_installed go raiserror('Creating procedure sp_MSunc_to_drive', 0,1) GO CREATE PROCEDURE sp_MSunc_to_drive ( @unc_path nvarchar(255), @local_server sysname, @local_path nvarchar(255) output ) AS SET NOCOUNT ON declare @pattern nvarchar(150) select @pattern = N'\\' + upper(@local_server) + N'\' if charindex(@pattern, upper(substring(@unc_path, 1, len(@pattern)))) <> 0 and charindex(N'$\', substring(@unc_path, len(@pattern)+2, 2))<>0 select @local_path = substring(@unc_path, len(@pattern) + 1, 1) + N':' + substring(@unc_path, len(@pattern) + 3, len(@unc_path) - len(@pattern) -1) else select @local_path = @unc_path GO exec dbo.sp_MS_marksystemobject sp_MSunc_to_drive go raiserror('Creating procedure sp_MSretrieve_publication_attributes', 0,1) GO create proc sp_MSretrieve_publication_attributes @name sysname, @database sysname AS SET NOCOUNT ON declare @mergepublish_bit int declare @tranpublish_bit int declare @procname nvarchar(640) declare @retcode int select @mergepublish_bit = 4 select @tranpublish_bit = 1 /* ** Security Check, will be checked inside sp_MSretrieve_publication ** and sp_MSretrieve_mergepublication */ create table #publication_property ( Name sysname collate database_default, dbanme sysname collate database_default, Publisher sysname collate database_default, Type nvarchar(15) collate database_default, Description nvarchar(255) collate database_default, Status tinyint, allow_pull bit, allow_sync_tran bit, allow_anonymous bit, allow_queued_tran bit, enabled_for_internet bit, third_party bit ) if (select category & @tranpublish_bit from master..sysdatabases where name = @database collate database_default) <> 0 begin select @procname = quotename(@database) + '.dbo.sp_MSretrieve_publication ' insert into #publication_property exec @retcode = @procname @name end if (select category & @mergepublish_bit from master..sysdatabases where name = @database collate database_default) <> 0 begin select @procname = quotename(@database) + '.dbo.sp_MSretrieve_mergepublication ' insert into #publication_property exec @retcode = @procname @name end select * from #publication_property drop table #publication_property Go exec dbo.sp_MS_marksystemobject sp_MSretrieve_publication_attributes go raiserror('Creating procedure sp_MScleanup_publication_ADinfo', 0,1) GO create proc sp_MScleanup_publication_ADinfo @name sysname, @database sysname AS SET NOCOUNT ON declare @mergepublish_bit int declare @tranpublish_bit int declare @cmd nvarchar(640) select @mergepublish_bit = 4 select @tranpublish_bit = 1 /* ** Security Check */ select @cmd = quotename(@database) + '.dbo.sp_MSreplcheck_publish' exec (@cmd) IF @@ERROR <> 0 return (1) if (select category & @tranpublish_bit from master..sysdatabases where name = @database collate database_default) <> 0 begin select @cmd = N'update' + quotename(@database) + N'.dbo.syspublications set ad_guidname=NULL where name=N' + quotename(@name, N'''') exec (@cmd) end if (select category & @mergepublish_bit from master..sysdatabases where name = @database collate database_default) <> 0 begin select @cmd = N'update' + quotename(@database) + N'.dbo.sysmergepublications set ad_guidname=NULL where name=N' + quotename(@name, N'''') exec (@cmd) end Go exec dbo.sp_MS_marksystemobject sp_MScleanup_publication_ADinfo go raiserror('Creating procedure sp_MSrepl_linkedservers_rowset', 0,1) GO create proc sp_MSrepl_linkedservers_rowset @srvname sysname as select SVR_NAME = srvname, SVR_PRODUCT = srvproduct, SVR_PROVIDERNAME = providername, SVR_DATASOURCE = datasource, SVR_PROVIDERSTRING = providerstring, SVR_LOCATION = location, SVR_CATALOG = catalog from master.dbo.sysservers where UPPER(srvname) = UPPER(@srvname) collate database_default and isnull(providername,' ') <> ' ' and ( isnull(datasource, ' ') <> ' ' or isnull(location, ' ') <> ' ' or isnull(providerstring, ' ') <> ' ' or isnull(catalog, ' ') <> ' ' ) order by 1 if @@error <> 0 return 1 else return 0 go exec dbo.sp_MS_marksystemobject sp_MSrepl_linkedservers_rowset go raiserror('Creating procedure sp_MSregistersubscription', 0,1) go CREATE PROCEDURE sp_MSregistersubscription ( @replication_type int, /* Transactional = 1, Merge = 2 */ @publisher sysname, @publisher_db sysname, @publisher_security_mode int = NULL, /* 0 standard; 1 integrated */ @publisher_login sysname = NULL, @publisher_password nvarchar(524) = NULL, @publication sysname, @subscriber sysname, @subscriber_db sysname, @subscriber_security_mode int = NULL, /* 0 standard; 1 integrated */ @subscriber_login sysname = NULL, @subscriber_password nvarchar(524) = NULL, @distributor sysname, @distributor_security_mode int = NULL, @distributor_login sysname = NULL, @distributor_password nvarchar(524) = NULL, @subscription_id uniqueidentifier , @independent_agent int = NULL, @subscription_type int, @use_interactive_resolver int = NULL, @failover_mode int = NULL ) AS SET NOCOUNT ON /* MobileSync Support */ declare @subscription_name nvarchar(1000) declare @regkey nvarchar(1000) declare @subidstr nvarchar(38) declare @profile_name nvarchar(100) declare @retcode int set @subscription_name = @publisher + ':' + @publisher_db + ':' + @publication + ':' + @subscriber + ':' + @subscriber_db /* Replace back slash with forward slash so that the key name is a valid REGISTRY key name */ set @subscription_name = REPLACE(@subscription_name,'\','/') set @regkey = 'SOFTWARE\Microsoft\Microsoft SQL Server\80\Replication\Subscriptions\' + @subscription_name set @subidstr = '{' + convert ( nchar(36), @subscription_id) + '}' set @profile_name = formatmessage(20550) -- SyncMgr Profile EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE', @regkey, 'ProfileName', 'REG_SZ', @profile_name if @retcode <> 0 OR @@ERROR <> 0 return 1 EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE', @regkey, 'ReplicationType', 'REG_DWORD', @replication_type if @retcode <> 0 OR @@ERROR <> 0 return 1 EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE', @regkey, 'SubscriptionType', 'REG_DWORD', @subscription_type if @retcode <> 0 OR @@ERROR <> 0 return 1 EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE', @regkey, 'Subid', 'REG_SZ', @subidstr if @retcode <> 0 OR @@ERROR <> 0 return 1 EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE', @regkey, 'Publisher', 'REG_SZ', @publisher if @retcode <> 0 OR @@ERROR <> 0 return 1 EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE', @regkey, 'PublisherDb', 'REG_SZ', @publisher_db if @retcode <> 0 OR @@ERROR <> 0 return 1 IF @use_interactive_resolver IS NOT NULL BEGIN EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE', @regkey, 'UseInteractiveResolver', 'REG_DWORD', @use_interactive_resolver if @retcode <> 0 OR @@ERROR <> 0 return 1 END /* If Publisher security mode is NOT NULL, write out the entries */ if @publisher_security_mode IS NOT NULL begin EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE', @regkey, 'PublisherSecurityMode', 'REG_DWORD', @publisher_security_mode if @retcode <> 0 OR @@ERROR <> 0 return 1 EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE', @regkey, 'PublisherLogin', 'REG_SZ', @publisher_login if @retcode <> 0 OR @@ERROR <> 0 return 1 end EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE', @regkey, 'Publication', 'REG_SZ', @publication if @retcode <> 0 OR @@ERROR <> 0 return 1 EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE', @regkey, 'Subscriber', 'REG_SZ', @subscriber if @retcode <> 0 OR @@ERROR <> 0 return 1 /* If Subscriber security mode is NOT NULL, write out the entries */ if @subscriber_security_mode IS NOT NULL begin EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE', @regkey, 'SubscriberSecurityMode', 'REG_DWORD', @subscriber_security_mode if @retcode <> 0 OR @@ERROR <> 0 return 1 EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE', @regkey, 'SubscriberLogin', 'REG_SZ', @subscriber_login if @retcode <> 0 OR @@ERROR <> 0 return 1 end EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE', @regkey, 'SubscriberDb', 'REG_SZ', @subscriber_db if @retcode <> 0 OR @@ERROR <> 0 return 1 EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE', @regkey, 'Distributor', 'REG_SZ', @distributor if @retcode <> 0 OR @@ERROR <> 0 return 1 /* If Distributor security mode is NOT NULL, write out the entries */ if @distributor_security_mode IS NOT NULL begin EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE', @regkey, 'DistributorSecurityMode', 'REG_DWORD', @distributor_security_mode if @retcode <> 0 OR @@ERROR <> 0 return 1 EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE', @regkey, 'DistributorLogin', 'REG_SZ', @distributor_login if @retcode <> 0 OR @@ERROR <> 0 return 1 end if @independent_agent IS NOT NULL begin EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE', @regkey, 'IndependentAgent', 'REG_DWORD', @independent_agent if @retcode <> 0 OR @@ERROR <> 0 return 1 end IF @failover_mode IS NOT NULL begin EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE', @regkey, 'FailoverMode', 'REG_DWORD', @failover_mode if @retcode <> 0 OR @@ERROR <> 0 return 1 end -- Mark enabled_for_syncmgr bit if every thing succeeded. -- If the row exists in MSreplication_properties table, -- set enabled_for_syncmgr bit -- The logic need to be here because UI call this sp directly. if exists (select * from sysobjects where name = 'MSsubscription_properties') begin update MSsubscription_properties set enabled_for_syncmgr = 1 where UPPER(publisher) = UPPER(@publisher) and publisher_db = @publisher_db and publication = @publication if @retcode <> 0 OR @@ERROR <> 0 return 1 end return 0 GO raiserror('Creating procedure sp_MSunregistersubscription', 0,1) go CREATE PROCEDURE sp_MSunregistersubscription @publisher sysname = NULL, @publisher_db sysname = NULL, @publication sysname = NULL, @subscriber sysname = NULL, @subscriber_db sysname = NULL AS /* ** Drop the corresponding registry entry for MobileSync */ declare @enabled int declare @retcode int declare @regkey nvarchar(1000) select @retcode = 0 -- Mark enabled_for_syncmgr bit before trying to delete the key -- If the row exists in MSreplication_properties table, -- set enabled_for_syncmgr bit -- The logic need to be here because UI call this sp directly. if exists (select * from sysobjects where name = 'MSsubscription_properties') begin update MSsubscription_properties set enabled_for_syncmgr = 0 where UPPER(publisher) = UPPER(@publisher) and publisher_db = @publisher_db and publication = @publication if @@ERROR <> 0 return 1 end -- regdelete returns 'Access Denied' message if key does not exist; check before delete exec sp_MSsubscription_enabled_for_syncmgr @publisher, @publisher_db, @publication, @subscriber, @subscriber_db, @enabled OUT, @regkey OUT if @@ERROR <> 0 return 1 if @enabled = 1 begin EXECUTE @retcode = master.dbo.xp_regdeletekey 'HKEY_LOCAL_MACHINE', @regkey if @@error <> 0 OR @retcode <> 0 return 1 end return 0 GO raiserror('Creating procedure sp_MSsubscription_enabled_for_syncmgr', 0,1) go CREATE PROCEDURE sp_MSsubscription_enabled_for_syncmgr @publisher sysname = NULL, @publisher_db sysname = NULL, @publication sysname = NULL, @subscriber sysname = NULL, @subscriber_db sysname = NULL, @enabled int = NULL OUTPUT, @regkey nvarchar(1000) = NULL OUTPUT AS /* ** Drop the corresponding registry entry for MobileSync */ declare @subscription_name nvarchar(1000) declare @keyexist int -- no reg key to clean up for virtual subscribers if @subscriber is null begin select @enabled = 0 return 0 end set @subscription_name = @publisher + ':' + @publisher_db + ':' + @publication + ':' + @subscriber + ':' + @subscriber_db /* Replace back slash with forward slash so that the key name is a valid REGISTRY key name */ set @subscription_name = REPLACE(@subscription_name,'\','/') set @regkey = 'SOFTWARE\Microsoft\Microsoft SQL Server\80\Replication\Subscriptions\' + @subscription_name create table #keyexist (keyexist int) insert into #keyexist EXECUTE master.dbo.xp_regread 'HKEY_LOCAL_MACHINE', @regkey select @enabled = keyexist from #keyexist drop table #keyexist return 0 GO raiserror('Creating procedure sp_MSget_jobstate', 0,1) go -- Procedure sp_MSget_jobstate -- The proc takes a specific Job ID and returns the Job State of the job -- Returns a row with one column job_state -- Returns a row with NULL if job does not exist -- CREATE PROCEDURE sp_MSget_jobstate @job_id UNIQUEIDENTIFIER AS BEGIN DECLARE @is_sysadmin INT DECLARE @job_owner sysname DECLARE @job_state INT DECLARE @job_id_as_char VARCHAR(36) SET NOCOUNT ON CREATE TABLE #xp_results (job_id UNIQUEIDENTIFIER NOT NULL, last_run_date INT NOT NULL, last_run_time INT NOT NULL, next_run_date INT NOT NULL, next_run_time INT NOT NULL, next_run_schedule_id INT NOT NULL, requested_to_run INT NOT NULL, -- BOOL request_source INT NOT NULL, request_source_id sysname collate database_default null, running INT NOT NULL, -- BOOL current_step INT NOT NULL, current_retry_attempt INT NOT NULL, job_state INT NOT NULL) -- Need a job_id if (@job_id IS NULL) BEGIN SELECT @job_id_as_char = CONVERT(VARCHAR(36), @job_id) RAISERROR(14262, -1, -1, '@job_id', @job_id_as_char) RETURN(1) -- Failure END -- Capture job execution information (for local jobs only since that's all SQLServerAgent caches) SELECT @is_sysadmin = ISNULL(IS_SRVROLEMEMBER(N'sysadmin'), 0) SELECT @job_owner = suser_sname(suser_sid()) INSERT INTO #xp_results EXECUTE master.dbo.xp_sqlagent_enum_jobs @is_sysadmin, @job_owner -- Select the job state of the job in question SELECT @job_state = job_state FROM #xp_results WHERE @job_id = job_id -- Error if we have no rows selected if (@job_state IS NULL) BEGIN SELECT @job_id_as_char = CONVERT(VARCHAR(36), @job_id) RAISERROR(14262, -1, -1, '@job_id', @job_id_as_char) RETURN(1) -- Failure END ELSE SELECT @job_state -- All done DROP TABLE #xp_results RETURN(0) -- Success END GO raiserror('Creating procedure sp_MSscript_pkvar_assignment', 0,1) go create procedure sp_MSscript_pkvar_assignment ( @objid int, @columns binary(32), @indent int = 0, @identity_col sysname = NULL, -- Not null value used by trigger scripting @ts_col sysname = NULL, -- Not null value used by trigger scripting @primary_key_bitmap varbinary(4000) = null, -- NULL when synctran processing @fisqueuedpub bit = 0 -- 1 = processing a queued publication on publisher ) as begin -- This stored procedure will assign the '_old' var to new var -- based on @bitmap. This is to avoid using case statement -- in the where clause in the synctran pub proc, which -- will cause a table scan. declare @cmd nvarchar(4000) ,@spacer nvarchar(20) ,@indkey int ,@indid int ,@this_col int ,@col sysname ,@qualname nvarchar(512) ,@column nvarchar(255) ,@key sysname ,@src_cols int ,@total_col int ,@fcreatedcolmap bit ,@art_col int -- relative position of column declare @colmap table (relativeorder int identity(1,1), colid int) select @spacer = N'select ' ,@cmd = N'' ,@indkey = 1 ,@indid = 0 ,@fcreatedcolmap = 0 exec sp_MSget_qualified_name @objid, @qualname OUTPUT select @src_cols = max(colid) ,@total_col = count(colid) from syscolumns where id = @objid exec dbo.sp_MSpad_command @cmd output, @indent exec dbo.sp_MSflush_command @cmd output, 1, @indent if @primary_key_bitmap is null begin exec @indid = dbo.sp_MStable_has_unique_index @objid if @indid is null begin raiserror('Debug: Cannot find unique index', 16, -1) return (1) end end -- -- check if column Id match relative column order -- for trigger scripting -- if ((@total_col < @src_cols) and (@columns is null) and (@primary_key_bitmap is not null)) begin -- -- this table may have altered columns, so when we need to -- set a mapping for using the bitmaps properly as the bitmap -- always refers relative column order -- insert into @colmap (colid) select colid from syscolumns where id = @objid order by colid if (@@error != 0) begin raiserror('Could not create column mapping', 16, -1) return (1) end select @fcreatedcolmap = 1 end while (1=1) begin if @primary_key_bitmap is null begin select @key = index_col(@qualname, @indid, @indkey) if @key is null break exec dbo.sp_MSget_col_position @objid, @columns, @key, @col output, 0, NULL, @this_col output end else begin exec dbo.sp_MSget_map_position @primary_key_bitmap, @indkey, @col output, @this_col output if @this_col is null break -- -- set the actual column id for this relative order in the PK bitmap if necessary -- if (@fcreatedcolmap = 1) begin select @art_col = @this_col select @this_col = colid ,@col = 'c' + convert(sysname, colid) from @colmap where relativeorder = @art_col end else begin select @art_col = NULL end -- Get column name exec dbo.sp_MSget_colinfo @objid, @this_col, @columns, 0, @key output end select @indkey = @indkey + 1 -- -- check if identity/timestamp column were specified -- for skipping during subscriber trigger scripting -- if @key in (@identity_col, @ts_col) continue -- -- If we are scripting on publisher -- if (@primary_key_bitmap is null) begin declare @isset int -- -- skip column if not replicated -- exec @isset = dbo.sp_isarticlecolbitset @this_col, @columns if (@isset != 1) continue -- -- skip timestamp processing for queued -- if ((@fisqueuedpub = 1) and exists (select name from syscolumns where id = @objid and colid = @this_col and xtype = 189)) continue end select @cmd = @spacer + N'@c' + convert(nvarchar(10), @this_col) -- Get the new values for the columns in primary key. exec dbo.sp_MSget_synctran_column @ts_col = null, @op_type = null , -- 'ins, 'upd', 'del' @is_new = null, @primary_key_bitmap = null, @colname = null, @this_col = @this_col, @column = @column output, @from_proc = 0, @coltype = null, @type = 'pk_var', @art_col = @art_col select @cmd = @cmd + N' = ' + @column select @spacer = ', ' -- flush command if necessary exec dbo.sp_MSflush_command @cmd output, 1, @indent end end go EXEC dbo.sp_MS_marksystemobject sp_MSscript_pkvar_assignment GO raiserror('Creating procedure sp_MSget_publication_from_taskname', 0,1) go create procedure sp_MSget_publication_from_taskname @taskname sysname, @publisher sysname, @publisherdb sysname, @publication sysname OUTPUT as declare @value sysname declare @value2 sysname declare @position INT select @publication = NULL -- Parse out publication name from the task name "publisher_publisherdb_publication_number" -- Expect publisher name if charindex(@publisher, @taskname) <> 1 begin return 1 end -- Eat up the publisher name select @value = stuff(@taskname, 1, len(@publisher), N'') -- Expect '_' + publisherdb + '_' select @value2 = N'_' + @publisherdb + N'_' if charindex(@value2, @value) <> 1 begin return 1 end -- Eat up '_' + publisherdb + '_' select @value = stuff(@value, 1, LEN(@publisherdb) + 2, N'') -- Reverse the string in the hope of finding the first '_' -- from the right which denotes the end of the publication -- name. The number at the end should not contain '_' select @value2 = reverse(@value) select @position = charindex(N'_', @value2) if @position < 2 begin return 1 end select @publication = left(@value, len(@value) - @position) return 0 go EXEC dbo.sp_MS_marksystemobject sp_MSget_publication_from_taskname go -- sp_MSacquireHeadofQueueLock, sp_MSacquireSlotLock and sp_MSreleaseSlotLock work together -- to ensure the number of concurrent merge processes does not exceed a given value. A merge -- process has to acquire headofqueue, i.e., Im-First lock before it can acquire slot lock. -- All merge processes are queued for the Im-First lock and only the one process holding that -- lock will poll to see if there is any slot available for it to get it. raiserror('Creating procedure sp_MSacquireHeadofQueueLock', 0,1) GO CREATE PROC sp_MSacquireHeadofQueueLock @process_name sysname, @queue_timeout int = 0, -- means wait inâ•–definitely @no_result bit = 0, @return_immediately bit = 0 -- if 1, do not wait: return and post a progress message. AS declare @entry_date datetime declare @delay_time int --in second declare @retcode int declare @max_waiting int declare @lock_acquired bit -- Security Checking -- sysadmin or db_owner or PAL user of any publication if not exists (select * from dbo.sysmergepublications where 1 = {fn ISPALUSER(pubid)}) begin RAISERROR (14260, 16, -1) return (1) end if @queue_timeout<0 begin raiserror(21344, 16, -1, '@queue_timeout') return (1) end if @queue_timeout> 3600*12 -- more than 12 hours is not allowed: make it 0 in this case. begin raiserror(21417, 16, -1) return (1) end --quick peek and leave if @return_immediately=1 begin --take a peek: return without wait regardless of whether the lock is successfully acquired. exec @retcode=sp_getapplock @Resource=@process_name,@LockMode=N'Exclusive',@LockOwner='Session',@LockTimeout=0 if (@retcode <> 0 AND @retcode <> -1) begin RAISERROR(21414,16,-1) RETURN(@retcode) end IF (@retcode = 0) -- AppLock acquired select 1, 0 -- 1 means lock acquired, 0 is the time consumed to acquired this lock. else if @retcode = -1 -- AppLock is not available select 0, 0 -- first 0 means lock not available, second column will be ignored. return (0) -- OK end -- from now on, @return_immediately=0 --if @queue_timeout=0, means waiting indefinitely if @queue_timeout=0 select @max_waiting = NULL else --otherwise convert to minisecond and pass it down. select @max_waiting = @queue_timeout * 1000 select @delay_time=0 select @entry_date=getdate() -- First try to acquire EXCLUSIVE lock which signfies at front of queue. i.e. I'm next. exec @retcode=sp_getapplock @process_name, @LockMode=N'Exclusive',@LockOwner=N'Session', @LockTimeout=@max_waiting -- We shouldn't return from above until we have it -- RC should be either 0 (got immediately) or 1 (waited and got it eventually) or -1 (timed out); Exit on anything else. -- We need value -1 because @LockTimeout value is no longer NULL, meaning waiting indefinitely. It is possible -- that we waited for a given length of time and timed out IF (@retcode <> 0 and @retcode <> 1) and @retcode<>-1 BEGIN RAISERROR(21413, 16, -1) RETURN(@retcode) END -- Im-first lock is to be released after successfully obtained a slot lock later. select @delay_time=datediff(ss, @entry_date, getdate()) if @retcode=-1 select @lock_acquired=0 else select @lock_acquired=1 if @no_result = 0 begin select @lock_acquired, @delay_time end RETURN(0) exec dbo.sp_MS_marksystemobject sp_MSacquireHeadofQueueLock go grant execute on dbo.sp_MSacquireHeadofQueueLock to public go -- this stored procedure is called by merge agent to limit the max number of -- concurrent merge processes at publisher side. The merge process that calls -- this SP must be the one that is currently holding HeadOfQueue lock. Once -- a slot lock is granted, HeadOfQueue lock will be released for use the next -- merge process waiting in the queue for that lock. -- @queue_timeout value gives -- the maximum length of time (in seconds) a merge agent would like to wait -- before acquring Im-first lock and the available serve slots. A value of 0 -- means it would wait indefinitely until getting the lock or being canceled -- by the caller of the procedure raiserror('Creating procedure sp_MSacquireSlotLock', 0,1) GO CREATE PROC sp_MSacquireSlotLock @process_name sysname, @concurrent_max int, @queue_timeout int = 0,-- means wait inâ•–definitely @return_immediately bit = 0 -- if set to 1, take a peek at the server and return immediately. AS declare @entry_date datetime declare @slot_name nvarchar(150) -- OUTPUT - must give back slot acquired to caller so caller can later release. declare @basetime datetime declare @delaytime datetime declare @retcode int declare @i int declare @lock_acquired bit -- Security Checking if not exists (select * from dbo.sysmergepublications where 1 = {fn ISPALUSER(pubid)}) begin RAISERROR (15247, 11, -1) return (1) end select @lock_acquired = 0 if @queue_timeout<0 begin raiserror(21344, 16, -1, '@queue_timeout') return (1) end if @concurrent_max<=0 begin raiserror(21344, 16, -1, '@concurrent_max') return (1) end select @entry_date=getdate() select @delaytime = '00:00:02' --polling interval is defaulted to 2 seconds SET @slot_name=NULL -- If terminate anywhere unexpectedly, dont want to give caller a lock they didnt really get. -- We are at front of queue, so check if any available 'slot' is open. -- We do not wait at all for these locks, and hence expect either it was granted or timed out (-1). SET @i=1 WHILE (@i <= @concurrent_max) BEGIN --the process has waited long enough. quit now and try later. If @queue_timeout is 0, keep waiting until succeeds. if @queue_timeout>0 and DATEADD(second, -@queue_timeout, getdate()) > @entry_date begin select @lock_acquired = 1 -- not a peek but has waited as specified select @slot_name = NULL -- waited but failed to get one BREAK end SET @slot_name=@process_name+convert(varchar,@i) --the call is not blocking, return immediately having acquired the lock or not exec @retcode=sp_getapplock @Resource=@slot_name,@LockMode=N'Exclusive',@LockOwner='Session',@LockTimeout=0 IF (@retcode <> 0 AND @retcode <> -1) BEGIN RAISERROR(21414,16,-1) RETURN(@retcode) END IF (@retcode = 0) -- got lock for that slot - cleanup and leave. BEGIN -- Release the "Im first lock" exec @retcode=sp_releaseapplock @process_name,@LockOwner=N'Session' IF (@retcode <> 0) BEGIN SET @slot_name=NULL RAISERROR(21415, 16, -1) RETURN(@retcode) END select @lock_acquired = 1 -- We got our slot and released the Im first lock. We're done. BREAK END ELSE IF (@retcode = -1) -- Couldn't immediately get the lock. So try the next one. BEGIN SET @i=@i+1 IF @i <= @concurrent_max CONTINUE -- restart the loop ELSE BEGIN -- Sleep and start over. if @return_immediately=1 begin select @lock_acquired = 0 --slot name does not matter in this case BREAK end else begin WAITFOR DELAY @delaytime SET @i=1 CONTINUE -- restart the loop end END END END --output the slot name for the purpose of releasing the lock by the caller --if the value if NULL, the caller does not acquire the lock select @lock_acquired, @slot_name RETURN(0) exec dbo.sp_MS_marksystemobject sp_MSacquireSlotLock go grant execute on dbo.sp_MSacquireSlotLock to public go -- this procedure is called by merge process to release slot lock -- that is acquired by calling sp_MSacquireSlotLock. raiserror('Creating procedure sp_MSreleaseSlotLock', 0,1) GO -- this stored procedure is called by merge agent to release the application lock -- acquired by sp_MSacquireSlotLock CREATE PROC sp_MSreleaseSlotLock @process_name sysname AS declare @retcode int -- Security Checking -- sysadmin or db_owner or PAL user have access if not exists (select * from dbo.sysmergepublications where 1 = {fn ISPALUSER(pubid)}) begin RAISERROR (15247, 11, -1) return (1) end exec @retcode=sp_releaseapplock @process_name,@LockOwner=N'Session' IF (@retcode <> 0) BEGIN RAISERROR(21415, 16, -1) return (1) END return @retcode GO exec dbo.sp_MS_marksystemobject sp_MSreleaseSlotLock go grant exec on dbo.sp_MSreleaseSlotLock to public go raiserror('Creating procedure sp_MSrepl_check_server', 0,1) go CREATE PROCEDURE sp_MSrepl_check_server ( @srvname sysname, @check_distdb bit = 0 ) AS -- This sp is called by sp_dropserver to check if the server is in use by replication. declare @subscriber_bit smallint declare @distributor_bit smallint declare @retcode int declare @proc nvarchar(255) declare @dbname sysname -- Intialize select @distributor_bit = 8 select @subscriber_bit = 4 if @check_distdb = 0 begin -- Check to see if the server is marked as a Distributor if exists (select * from sysservers where UPPER(srvname) = UPPER(@srvname) and srvstatus & @distributor_bit <> 0) begin raiserror(20581, 16, -1, @srvname) return (1) end -- Check to see if the server is marked as a subscriber if exists (select * from sysservers where UPPER(srvname) = UPPER(@srvname) and srvstatus & @subscriber_bit <> 0) begin raiserror(20583, 16, -1, @srvname) return (1) end -- Check to see if the server is a dist publisher if object_id('msdb.dbo.MSdistpublishers') is not null begin if exists (select * from msdb.dbo.MSdistpublishers where UPPER(name) = UPPER(@srvname) collate database_default) begin raiserror(20582, 16, -1, @srvname) return (1) end end -- Check to see if the server is in use as a subscriber in the distribution dbs. if object_id('msdb.dbo.MSdistributiondbs') is not null begin declare hCForEachDb CURSOR LOCAL FAST_FORWARD FOR select name from msdb.dbo.MSdistributiondbs FOR READ ONLY open hCForEachDb fetch hCForEachDb into @dbname /* Loop for each database */ while (@@fetch_status >= 0) begin select @proc = quotename(@dbname) + '.dbo.sp_MSrepl_check_server' exec @retcode = @proc @srvname = @srvname, @check_distdb = 1 if @retcode <> 0 or @@error <> 0 return (1) fetch hCForEachDb into @dbname end /* while FETCH_SUCCESS */ end end else begin if object_id('MSsubscriber_info') is not null begin declare @publisher sysname select @publisher = publisher from MSsubscriber_info sub where UPPER(subscriber) = UPPER(@srvname) if @publisher is not null begin raiserror(20584, 16, -1, @srvname, @publisher) return (1) end end end GO EXEC dbo.sp_MS_marksystemobject sp_MSrepl_check_server go raiserror('Creating procedure sp_MSreset_synctran_bit', 0,1) go CREATE PROCEDURE sp_MSreset_synctran_bit ( @owner sysname, @table sysname )AS declare @qualified_name nvarchar(300) declare @synctran_bit int select @synctran_bit = 256 if @owner = N'' select @qualified_name = @table else select @qualified_name = quotename(@owner) + '.' + quotename(@table) -- Unmark synctran bit update sysobjects set replinfo = replinfo & ~@synctran_bit where id = object_id(@qualified_name) and (replinfo & @synctran_bit) <> 0 IF @@ERROR <> 0 return(1) return(0) GO EXEC dbo.sp_MS_marksystemobject sp_MSreset_synctran_bit go grant execute on dbo.sp_MSreset_synctran_bit to public go -- -- Name: sp_MSenum_replsqlqueues -- -- Description: Proc that enumerates all the subscriber + subscriber_db for the currently -- active queued subscriptions in all the distribution databases in this system. Invoked on -- Distributor for SQL based queues in Updating subscribers by Queue reader Agent -- -- Parameter : -- @curdistdb sysname : specified distribution database. If NULL, then -- enumerate the queues for all the distribution databases -- -- Owner: KaushikC -- -- Returns: 0 - succeeded -- 1 - failed -- -- Resultset: -- publisher sysname collate database_default not null, -- publisher_db sysname collate database_default not null, -- subscriber sysname collate database_default not null, -- subscriber_db sysname collate database_default not null, -- publication sysname collate database_default not null, -- dist_db sysname collate database_default not null -- -- Security: Procedural security check is done inside this procedure -- to make sure that the caller is either a member of the db_owner -- role of the distribution database or a member of the sysadmin role -- raiserror('Creating procedure sp_MSenum_replsqlqueues', 0,1) go create procedure sp_MSenum_replsqlqueues ( @curdistdb sysname = NULL ) as begin declare @distbit int declare @db_name sysname declare @cmd nvarchar(1024) select @distbit = 16 -- -- security check -- if (is_srvrolemember('sysadmin') != 1) begin -- -- non SA user -- @curdistdb cannot be null for NON-SA user -- if (@curdistdb is null) begin raiserror (14043, 16, -1, '@curdistdb') return 1 end else begin -- -- The user has to be DBO of the specified distribution db -- declare @fisdbo bit ,@securitycmd nvarchar(300) select @securitycmd = quotename(@curdistdb) + '.dbo.sp_executesql' exec @securitycmd N'if is_member(N''db_owner'') = 1 set @fisdbo = 1' ,N'@fisdbo bit output' ,@fisdbo output if (@fisdbo != 1) begin raiserror (21050, 14, 3) return 1 end end end -- -- create the temp table to store the relevant information -- create table #replqueue ( publisher sysname collate database_default not null, publisher_db sysname collate database_default not null, subscriber sysname collate database_default not null, subscriber_db sysname collate database_default not null, publication sysname collate database_default not null, dist_db sysname collate database_default not null ) create unique index ucreplqueue ON #replqueue (subscriber, subscriber_db, publication) -- -- Has the user specified a distribution database -- if (@curdistdb is NULL) begin -- -- Go through all the distribution databases -- declare hCdatabase CURSOR LOCAL FAST_FORWARD FOR select name from master.dbo.sysdatabases where category & @distbit <> 0 and has_dbaccess(name) = 1 for read only end else begin -- -- User specified Distribution Database -- Validate the user specified name -- if exists (select name from master.dbo.sysdatabases where name = @curdistdb and category & @distbit <> 0 and has_dbaccess(name) = 1) begin declare hCdatabase CURSOR LOCAL FAST_FORWARD FOR select @curdistdb for read only end else begin -- -- Error : Invalid distribution db specified -- raiserror(20587, 16, 3, N'@curdistdb', N'sp_MSenum_replsqlqueues') return 1 end end -- -- Enumerate -- open hCdatabase fetch next from hCdatabase into @db_name while (@@fetch_status <> -1) begin select @cmd = 'SET NOCOUNT ON ' + 'INSERT INTO #replqueue (publisher, publisher_db, subscriber, subscriber_db, publication, dist_db) ' + 'SELECT c.srvname, a.publisher_db, b.srvname, a.subscriber_db, a.publication, N''' + @db_name + ''' ' + 'FROM ' + QUOTENAME(@db_name) + '.dbo.MSdistribution_agents as a ' + 'JOIN master.dbo.sysservers as b ' + 'ON a.subscriber_id = b.srvid ' + 'JOIN master.dbo.sysservers as c ' + 'ON a.publisher_id = c.srvid ' + 'WHERE substring(queue_id, 1, 10) = N''mssqlqueue'' ' exec (@cmd) fetch next from hCdatabase into @db_name end close hCdatabase deallocate hCdatabase -- -- select the contents of the temp table -- select * from #replqueue -- -- cleanup -- drop table #replqueue end go EXEC dbo.sp_MS_marksystemobject sp_MSenum_replsqlqueues go -- -- Name: sp_MSenum_replqueues -- -- Description: Proc that enumerates all the all the MSMQ based queues that -- are currently active in the specified distribution database. Invoked on -- Distributor for SQL based queues in Updating subscribers by Queue reader Agent -- -- Owner: KaushikC -- -- Parameter : -- @curdistdb sysname : specified distribution database. If NULL, then -- enumerate the queues for all the distribution databases -- -- Returns: 0 - succeeded -- 1 - failed -- -- Resultset: -- queue_server sysname collate database_default not null, -- queue_id sysname collate database_default not null, -- dist_db sysname collate database_default not null -- -- Security: Procedural security check is done inside this procedure -- to make sure that the caller is either a member of the db_owner -- role of the distribution database or a member of the sysadmin role -- raiserror('Creating procedure sp_MSenum_replqueues', 0,1) go create procedure sp_MSenum_replqueues ( @curdistdb sysname = NULL ) as begin declare @distbit int declare @db_name sysname declare @cmd nvarchar(1024) select @distbit = 16 -- -- security check -- if (is_srvrolemember('sysadmin') != 1) begin -- -- non SA user -- @curdistdb cannot be null for NON-SA user -- if (@curdistdb is null) begin raiserror (14043, 16, -1, '@curdistdb') return 1 end else begin -- -- The user has to be DBO of the specified distribution db -- declare @fisdbo bit ,@securitycmd nvarchar(300) select @securitycmd = quotename(@curdistdb) + '.dbo.sp_executesql' exec @securitycmd N'if is_member(N''db_owner'') = 1 set @fisdbo = 1' ,N'@fisdbo bit output' ,@fisdbo output if (@fisdbo != 1) begin raiserror (21050, 14, 3) return 1 end end end -- -- create the temp table to store the relevant information -- create table #replqueue ( queue_server sysname collate database_default not null, queue_id sysname collate database_default not null, dist_db sysname collate database_default not null ) create unique clustered index ucreplqueue ON #replqueue (queue_id) -- -- Has the user specified a distribution database -- if (@curdistdb is NULL) begin -- -- Go through all the distribution databases -- declare hCdatabase CURSOR LOCAL FAST_FORWARD FOR select name from master.dbo.sysdatabases where category & @distbit <> 0 and has_dbaccess(name) = 1 for read only end else begin -- -- User specified Distribution Database -- Validate the user specified name -- if exists (select name from master.dbo.sysdatabases where name = @curdistdb and category & @distbit <> 0 and has_dbaccess(name) = 1) begin declare hCdatabase CURSOR LOCAL FAST_FORWARD FOR select @curdistdb for read only end else begin -- -- Error : Invalid distribution db specified -- raiserror(20587, 16, 4, N'@curdistdb', N'sp_MSenum_replqueues') return 1 end end -- -- Enumerate -- open hCdatabase fetch next from hCdatabase into @db_name while (@@fetch_status <> -1) begin select @cmd = 'SET NOCOUNT ON ' + 'INSERT INTO #replqueue (queue_server, queue_id, dist_db) ' + 'SELECT queue_server, queue_id, ' + 'N''' + replace(@db_name, '''', '''''') + ''' ' + 'FROM ' + QUOTENAME(@db_name) + '.dbo.MSdistribution_agents ' + 'WHERE ' + 'queue_id IS NOT NULL and substring(queue_id, 1, 10) != N''mssqlqueue''' exec (@cmd) fetch next from hCdatabase into @db_name end close hCdatabase deallocate hCdatabase -- -- select the contents of the temp table to present -- the formatted queue name -- select N'DIRECT=OS:' + queue_server + N'\PRIVATE$\' + queue_id AS 'queue_format' ,dist_db from #replqueue -- -- cleanup -- drop table #replqueue end go EXEC dbo.sp_MS_marksystemobject sp_MSenum_replqueues go raiserror('Creating procedure sp_browsemergesnapshotfolder', 0,1) go CREATE PROCEDURE sp_browsemergesnapshotfolder ( @publication sysname ) AS BEGIN SET NOCOUNT ON DECLARE @dbname sysname DECLARE @alt_directory_type INT DECLARE @directory_type INT SELECT @alt_directory_type = 25 SELECT @directory_type = 7 if (1 <> is_member('db_owner')) begin RAISERROR (15247, 11, -1) return (1) end IF (EXISTS (SELECT * FROM sysobjects WHERE name = N'sysmergepublications')) AND (EXISTS (SELECT * FROM sysobjects WHERE name = N'sysmergeschemachange')) BEGIN SELECT 'snapshot_folder' = schematext FROM sysmergeschemachange sc INNER JOIN sysmergepublications mp ON sc.pubid = mp.pubid WHERE mp.name = @publication AND upper(mp.publisher) = upper(@@servername) AND publisher_db = db_name() AND (schematype = @directory_type OR schematype = @alt_directory_type) ORDER BY schematype desc END ELSE BEGIN SELECT @dbname = DB_NAME() RAISERROR(21147, 16, -1, @dbname) RETURN 1 END END GO EXEC dbo.sp_MS_marksystemobject sp_browsemergesnapshotfolder go raiserror('Creating procedure sp_browsesnapshotfolder', 0,1) go CREATE PROCEDURE sp_browsesnapshotfolder ( @publication sysname, @subscriber sysname = NULL, @subscriber_db sysname = NULL ) AS BEGIN SET NOCOUNT ON DECLARE @retcode INT DECLARE @publisher sysname DECLARE @publisher_db sysname DECLARE @distributor sysname DECLARE @distributiondb sysname DECLARE @distproc nvarchar(300) DECLARE @article_id INT SELECT @retcode = 0 SELECT @publisher = NULL SELECT @publisher_db = DB_NAME() SELECT @distributor = NULL SELECT @distributiondb = NULL SELECT @article_id = NULL EXEC @retcode = dbo.sp_MSreplcheck_publish IF @@ERROR <> 0 or @retcode <> 0 return (1) -- Either both of @subscriber and @subscriber_db are NULL or -- both of them have to be non-null IF ((@subscriber IS NULL OR @subscriber = N'') AND @subscriber_db IS NOT NULL AND @subscriber_db <> N'') OR ((@subscriber_db IS NULL OR @subscriber_db = N'') AND @subscriber IS NOT NULL AND @subscriber <> N'') BEGIN RAISERROR(21148, 16, -1) END IF EXISTS (SELECT * FROM sysobjects WHERE name = N'syspublications') AND EXISTS (SELECT * FROM sysobjects WHERE name = N'sysextendedarticlesview') BEGIN SELECT @publisher = @@SERVERNAME -- Get the smallest article id for the publication since -- method for identifying a publication is not readily available -- on the distributor SELECT @article_id = MIN(artid) FROM sysextendedarticlesview sa INNER JOIN syspublications sp ON sa.pubid = sp.pubid WHERE sp.name = @publication IF @article_id IS NULL BEGIN RAISERROR(20026, 16, -1, @publication) END EXEC @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT, @distribdb = @distributiondb OUTPUT IF @retcode <> 0 RETURN @retcode SELECT @distributor = RTRIM(@distributor) IF LOWER(@@SERVERNAME) <> LOWER(@distributor) BEGIN SELECT @distproc = @distributor + '.' + @distributiondb + '.dbo.sp_MSbrowsesnapshotfolder' END ELSE BEGIN SELECT @distproc = @distributiondb + '.dbo.sp_MSbrowsesnapshotfolder' END EXECUTE @retcode = @distproc @publisher = @publisher, @publisher_db = @publisher_db, @article_id = @article_id, @subscriber = @subscriber, @subscriber_db = @subscriber_db RETURN @retcode END ELSE BEGIN RAISERROR(21149, 16, -1, @publisher_db) RETURN 1 END END GO EXEC dbo.sp_MS_marksystemobject sp_browsesnapshotfolder go raiserror('Creating procedure sp_MScopysnapshot', 0,1) go CREATE PROCEDURE sp_MScopysnapshot ( @source_folder nvarchar(255), @destination_folder nvarchar(255) ) AS BEGIN SET NOCOUNT ON DECLARE @directory_exists bit DECLARE @ftporuncdir nvarchar(5) DECLARE @pubdir nvarchar(255) DECLARE @timestampdir nvarchar(255) DECLARE @bslashindex int DECLARE @bslashindex2 int DECLARE @bslashcounter int DECLARE @command nvarchar(1000) DECLARE @retcode int DECLARE @platform_nt bit IF platform() & 0x1 = 0x1 SELECT @platform_nt = 1 ELSE SELECT @platform_nt = 0 -- If @source_folder is NULL then either the snapshot has not been -- generated or it has been cleaned up IF @source_folder IS NULL OR @source_folder = N'' BEGIN RAISERROR(21289, 16, -1) RETURN (1) END -- Make sure that the @destination folder is not null IF @destination_folder IS NULL OR @destination_folder = N'' BEGIN RAISERROR(21287, 16, -1) RETURN (1) END -- Append backslash to @destination_folder if it is not -- there already IF SUBSTRING(@destination_folder, LEN(@destination_folder), 1) <> N'\' BEGIN SELECT @destination_folder = @destination_folder + N'\' END -- Check if the destination folder exists EXEC sp_MSget_file_existence @destination_folder, @directory_exists OUTPUT IF @directory_exists = 0 BEGIN RAISERROR(21287, 16, -1) RETURN (1) END -- Parse out the last three components in the source folder -- Note that the source_folder must have a trailing backslash SELECT @bslashindex = 1 SELECT @bslashindex2 = 1 SELECT @bslashcounter = 0 WHILE (@bslashindex <> 0) BEGIN SELECT @bslashindex = CHARINDEX(N'\', @source_folder, @bslashindex + 1) SELECT @bslashcounter = @bslashcounter + 1 IF @bslashcounter > 4 BEGIN SELECT @bslashindex2 = CHARINDEX(N'\', @source_folder, @bslashindex2 + 1) END END SELECT @bslashindex = CHARINDEX(N'\', @source_folder, @bslashindex2 + 1) SELECT @ftporuncdir = SUBSTRING(@source_folder, @bslashindex2 + 1, @bslashindex - @bslashindex2 - 1) SELECT @bslashindex2 = @bslashindex SELECT @bslashindex = CHARINDEX(N'\', @source_folder, @bslashindex2 + 1) SELECT @pubdir = SUBSTRING(@source_folder, @bslashindex2 + 1, @bslashindex - @bslashindex2 - 1) SELECT @bslashindex2 = @bslashindex SELECT @bslashindex = CHARINDEX(N'\', @source_folder, @bslashindex2 + 1) SELECT @timestampdir = SUBSTRING(@source_folder, @bslashindex2 + 1, @bslashindex - @bslashindex2 - 1) SELECT @bslashindex2 = @bslashindex -- Create the subdirectory structure underneath the specified snapshot -- folder. Ignore errors for now, we will check whether the directory -- is successfully created later on. -- Don't suppress output from xp_cmdshell so user knows what's going on -- in case something goes wrong SELECT @destination_folder = @destination_folder + @ftporuncdir + '\' SELECT @command = 'mkdir "' + fn_escapecmdshellsymbolsremovequotes(@destination_folder) collate database_default + '"' IF (@platform_nt = 1) SELECT @command = '" ' + @command + ' "' EXEC master..xp_cmdshell @command SELECT @destination_folder = @destination_folder + @pubdir + '\' SELECT @command = 'mkdir "' + fn_escapecmdshellsymbolsremovequotes(@destination_folder) collate database_default + '"' IF (@platform_nt = 1) SELECT @command = '" ' + @command + ' "' EXEC master..xp_cmdshell @command SELECT @destination_folder = @destination_folder + @timestampdir + '\' SELECT @command = 'mkdir "' + fn_escapecmdshellsymbolsremovequotes(@destination_folder) collate database_default + '"' IF (@platform_nt = 1) SELECT @command = '" ' + @command + ' "' EXEC master..xp_cmdshell @command -- Check if the real destination folder exists EXEC sp_MSget_file_existence @destination_folder, @directory_exists OUTPUT IF @directory_exists = 0 BEGIN RAISERROR(21288, 16, -1) RETURN (1) END -- Do the actual copying SELECT @command = 'copy "' + fn_escapecmdshellsymbolsremovequotes(@source_folder) collate database_default + '*.*" "' + fn_escapecmdshellsymbolsremovequotes(@destination_folder) collate database_default + '"' IF (@platform_nt = 1) SELECT @command = '" ' + @command + ' "' EXEC @retcode = master..xp_cmdshell @command IF @retcode <> 0 RETURN (1) ELSE RETURN (0) END go EXEC dbo.sp_MS_marksystemobject sp_MScopysnapshot go raiserror('Creating procedure sp_copymergesnapshot', 0,1) go CREATE PROCEDURE sp_copymergesnapshot ( @publication sysname, @destination_folder nvarchar(255) ) AS BEGIN SET NOCOUNT ON DECLARE @retcode int DECLARE @source_folder nvarchar(255) SELECT @retcode = 0 EXEC @retcode = dbo.sp_MSreplcheck_publish IF @@ERROR <> 0 OR @retcode <> 0 RETURN (1) CREATE TABLE #snapshot_folders ( id int identity, snapshot_folder nvarchar(255) collate database_default ) IF @@ERROR <> 0 BEGIN RETURN 1 END INSERT INTO #snapshot_folders EXEC @retcode = sp_browsemergesnapshotfolder @publication = @publication IF @retcode <> 0 OR @@ERROR <> 0 BEGIN GOTO Failure END SELECT @source_folder = (select top 1 snapshot_folder FROM #snapshot_folders ORDER BY id ASC) IF @@ERROR <> 0 BEGIN GOTO Failure END SET ROWCOUNT 0 EXEC @retcode = sp_MScopysnapshot @source_folder, @destination_folder IF @retcode <> 0 OR @@ERROR <> 0 BEGIN GOTO Failure END DROP TABLE #snapshot_folders RETURN 0 Failure: SET ROWCOUNT 0 DROP TABLE #snapshot_folders RETURN 1 END GO EXEC dbo.sp_MS_marksystemobject sp_copymergesnapshot go raiserror('Creating procedure sp_copysnapshot', 0,1) go CREATE PROCEDURE sp_copysnapshot ( @publication sysname, @destination_folder nvarchar(255), @subscriber sysname = NULL, @subscriber_db sysname = NULL ) AS BEGIN SET NOCOUNT ON DECLARE @retcode int DECLARE @source_folder nvarchar(255) SELECT @retcode = 0 -- security check, db_owner EXEC @retcode = dbo.sp_MSreplcheck_publish IF @@ERROR <> 0 or @retcode <> 0 return (1) CREATE TABLE #snapshot_folders ( id int identity, snapshot_folder nvarchar(255) collate database_default ) IF @@ERROR <> 0 BEGIN RETURN 1 END INSERT INTO #snapshot_folders EXEC @retcode = sp_browsesnapshotfolder @publication = @publication, @subscriber = @subscriber, @subscriber_db = @subscriber_db IF @retcode <> 0 OR @@ERROR <> 0 BEGIN GOTO Failure END SELECT @source_folder = (select top 1 snapshot_folder FROM #snapshot_folders ORDER BY id) IF @@ERROR <> 0 BEGIN GOTO Failure END SET ROWCOUNT 0 EXEC @retcode = sp_MScopysnapshot @source_folder, @destination_folder IF @retcode <> 0 OR @@ERROR <> 0 BEGIN GOTO Failure END DROP TABLE #snapshot_folders RETURN 0 Failure: SET ROWCOUNT 0 DROP TABLE #snapshot_folders RETURN 1 END GO EXEC dbo.sp_MS_marksystemobject sp_copysnapshot go raiserror('Creating procedure sp_MSrepl_validate_dts_package', 0,1) go CREATE PROCEDURE sp_MSrepl_validate_dts_package ( @name sysname ) AS SET NOCOUNT ON /* ** Declarations. */ if not exists (select * from msdb.dbo.sysdtspackages where name = @name) begin raiserror(21171, 16, -1, @name, @@servername ) return 1 end go EXEC dbo.sp_MS_marksystemobject sp_MSrepl_validate_dts_package go grant execute on dbo.sp_browsemergesnapshotfolder to public go grant execute on dbo.sp_browsesnapshotfolder to public go grant execute on dbo.sp_copymergesnapshot to public go grant execute on dbo.sp_copysnapshot to public go grant execute on dbo.sp_MSenum_replsqlqueues to public grant execute on dbo.sp_MSenum_replqueues to public go raiserror('Creating procedure sp_MSget_load_hint', 0,1) go create procedure sp_MSget_load_hint @objname sysname, @type int as declare @objid int declare @tabname sysname declare @tabid int declare @hint nvarchar(2048) declare @i int declare @thiskey sysname declare @indid smallint declare @indstat int select @objid = object_id( @objname ) if exists ( select * from sysobjects where id = @objid and type = 'V' ) begin select @tabid = depid from sysdepends where id = object_id( @objname ) select @tabname = object_name( @tabid ) select @indid = indid, @indstat = status from sysindexes where id = @tabid and ( status & @type ) = @type if @indid is not null begin create table #colnames ( idxcolname sysname collate database_default) select @thiskey = index_col( @tabname, @indid, 1 ) select @i = 2 while (@thiskey is not null ) begin insert into #colnames( idxcolname ) values( @thiskey ) select @thiskey = index_col(@tabname, @indid, @i) select @i = @i + 1 end if exists ( select idxcolname from #colnames where idxcolname not in (select name from syscolumns where id = object_id( @objname ) ) ) begin select @tabid = 0 end drop table #colnames end else begin select @tabid = 0 end end else begin select @tabname = @objname select @tabid = object_id( @objname ) select @indid = indid, @indstat = status from sysindexes where id = @tabid and ( status & @type ) = @type if @indid is null begin select @tabid = 0 end end -- Check for computed columns in chosen index. If computed columns exist, -- don't return a load hint. if @indid is not null begin select @i = 1 select @thiskey = index_col( @tabname, @indid, @i ) while @thiskey is not null begin if isnull( columnproperty( @tabid, @thiskey, 'IsComputed' ), 0 ) = 1 begin select @indid = null, @tabid = 0 break end select @i = @i + 1 select @thiskey = index_col( @tabname, @indid, @i ) end end if @tabid <> 0 begin select @hint = 'ORDER( '+QUOTENAME(index_col( @tabname, @indid, 1 )) collate database_default select @thiskey = index_col( @tabname, @indid, 2 ) select @i = 3 while (@thiskey is not null ) begin select @hint = @hint + ',' + QUOTENAME(@thiskey) collate database_default select @thiskey = index_col(@tabname, @indid, @i) select @i = @i + 1 end select @hint = @hint + ' ASC)' select @hint, @indstat end GO EXEC dbo.sp_MS_marksystemobject sp_MSget_load_hint go grant execute on dbo.sp_MSget_load_hint to public go raiserror('Creating procedure sp_getsubscriptiondtspackagename', 0,1) go CREATE PROCEDURE sp_getsubscriptiondtspackagename ( @publication sysname, @subscriber sysname = NULL ) AS SET NOCOUNT ON declare @name sysname declare @name_full sysname declare @id int select @id = 1 select @name = @publication if @subscriber is not null select @name = @name + N'_' + @subscriber -- reserver space for numbers to make the name unique select @name = substring(@name, 1, 100) select @name_full = @name while (1=1) begin if not exists (select * from msdb.dbo.sysdtspackages where name = @name_full) break select @name_full = @name + '_' + convert(nvarchar(10), @id) select @id = @id + 1 end select N'new_package_name' = @name_full go EXEC dbo.sp_MS_marksystemobject sp_getsubscriptiondtspackagename go grant execute on dbo.sp_getsubscriptiondtspackagename to public go raiserror('Creating procedure sp_MSverifytranfilter', 0, 1) GO create procedure sp_MSverifytranfilter @objid int as DECLARE @artname sysname DECLARE @sync_objid int DECLARE @qual_sync_object nvarchar(1024) DECLARE #testcursor CURSOR LOCAL FAST_FORWARD for SELECT name, sync_objid from sysarticles WHERE objid = @objid open #testcursor fetch #testcursor into @artname, @sync_objid while @@fetch_status <> -1 begin select @qual_sync_object = quotename( user_name(objectproperty(@sync_objid,'OwnerId'))) collate database_default + N'.' + quotename(object_name(@sync_objid)) collate database_default exec ( N'declare @var int select @var = count(*) from '+ @qual_sync_object + N' where 0 = 1' ) if @@ERROR<> 0 BEGIN raiserror( 14090, 16, -1, @artname ) return 1 END fetch #testcursor into @artname, @sync_objid end close #testcursor deallocate #testcursor return 0 GO EXEC dbo.sp_MS_marksystemobject sp_MSverifytranfilter go raiserror('Creating procedure sp_repldropcolumn', 0,1) GO CREATE PROCEDURE sp_repldropcolumn( @source_object nvarchar(270), @column sysname, @from_agent int = 0, @schema_change_script nvarchar(4000) = NULL, @force_invalidate_snapshot bit = 1, /* Force invalidate existing snapshot */ @force_reinit_subscription bit = 0 /* Force reinit subscription */ ) as set nocount on declare @objid int declare @at_publisher bit declare @pubname sysname declare @artname sysname declare @tran_pubname sysname declare @tran_artname sysname declare @tran_artid int declare @tran_pubid int declare @colid int declare @missing_index int declare @tablename sysname declare @pubid uniqueidentifier declare @artid uniqueidentifier declare @partitioned int declare @missing_count int declare @missing_bm varbinary(32) declare @old_missing_bm varbinary(32) declare @schematext nvarchar(4000) declare @schemaversion int declare @not_for_merge bit declare @qual_source_object nvarchar(262) declare @qual_dest_object nvarchar(262) declare @schematype int declare @schemaguid uniqueidentifier declare @conflict_table sysname declare @ins_conflict_proc sysname declare @publisher sysname declare @publisher_db sysname declare @command nvarchar(3000) declare @sync_objid int declare @retcode int declare @snapshot_ready int declare @con_id int declare @dest_owner sysname declare @dest_object nvarchar(386) declare @owner sysname declare @columnbm varbinary(128) declare @in_partition int declare @merge_pub_object_bit int declare @is_for_merge bit declare @is_for_tran bit declare @no_schema_replication bit declare @servername sysname declare @dbname sysname declare @con_name sysname declare @v_unique_index int declare @qual_column nvarchar(140) declare @indid int declare @index_cnt int declare @pkkey sysname declare @v_unique_constraint int declare @merge_pub_unmarkcolumn_bit int declare @merge_pub_markcolumn_bit int declare @schema_start_lsn binary(10) declare @schema_end_lsn binary(10) /* ** Security Check */ EXEC @retcode = dbo.sp_MSreplcheck_publish IF @@ERROR <> 0 or @retcode <> 0 return (1) -- check to see if this stored procedure is called via replication agent. if sessionproperty('replication_agent')<>1 select @from_agent = 0 else select @from_agent = 1 select @merge_pub_markcolumn_bit = 0x4000 select @merge_pub_unmarkcolumn_bit = ~@merge_pub_markcolumn_bit select @v_unique_constraint = 4096 select @v_unique_index = 2 -- status in sysindexes select @qual_column=QUOTENAME(@column) select @no_schema_replication = 0 select @not_for_merge = 0 select @merge_pub_object_bit = 128 select @objid = object_id(@source_object) select @servername=@@SERVERNAME select @dbname=db_name() if @objid is NULL begin --if table does not exists and the SP is called from replication agent, ignore the error and exit with success. if @from_agent=1 return (0) else begin raiserror(14027, 16, -1, @source_object) return (1) end end if not exists (select * from syscolumns where name=@column and id=@objid) begin if @from_agent=0 begin raiserror(21166, 16, -1, @column) return (1) end else return (0) end select @indid = indid from sysindexes where id = @objid and (status & 2048) <> 0 /* PK index */ select @index_cnt = 1 while (@index_cnt <= 16) begin select @pkkey = INDEX_COL(@source_object, @indid, @index_cnt) if @pkkey is NULL break if @pkkey=@column begin raiserror(21264, 16, -1, @column, @source_object) return (1) end select @index_cnt = @index_cnt + 1 end /* ** Check for unique index defined on this column - to disallow such a column from being dropped */ if exists (select * from sysindexes where id=@objid and (status & @v_unique_index = @v_unique_index or status & @v_unique_constraint = @v_unique_constraint)) begin declare @keys varbinary(816) declare @i int declare #check_unique CURSOR LOCAL FAST_FORWARD for select indid from sysindexes where id=@objid and (status & @v_unique_index = @v_unique_index or status & @v_unique_constraint = @v_unique_constraint) open #check_unique fetch #check_unique into @indid while (@@fetch_status<>-1) begin SELECT @i = 1 WHILE (@i <= 16) BEGIN SELECT @pkkey = INDEX_COL(@source_object, @indid, @i) if @pkkey is NULL break if @pkkey=@column BEGIN raiserror(21265, 16, -1, @column, @source_object) close #check_unique deallocate #check_unique return (1) END select @i = @i + 1 END fetch #check_unique into @indid end close #check_unique deallocate #check_unique end if exists (select * from sysobjects where name='sysmergearticles') begin if @from_agent=0 and exists (select * from sysmergearticles where objid=@objid and pubid not in (select pubid from sysmergepublications where LOWER(publisher)=LOWER(@@SERVERNAME) and publisher_db=db_name())) begin raiserror(21260, 16, -1, @dbname, @servername, @source_object) return (1) end end -- if not for TRAN, it has to be a merge publication if not exists (select * from sysobjects where name='syspublications') begin if not exists (select * from sysmergearticles where objid=@objid) select @no_schema_replication = 1 end -- if not for merge, it has to be a tran publication if not exists (select * from sysobjects where name='sysmergepublications') begin if not exists (select * from sysarticles where objid=@objid) select @no_schema_replication =1 end if exists (select * from sysobjects where name='sysmergepublications') and exists (select * from sysobjects where name='syspublications') begin if not exists (select * from sysarticles where objid=@objid) and not exists (select * from sysmergearticles where objid=@objid) select @no_schema_replication=1 end if @no_schema_replication=1 begin raiserror(21246, 16, -1, @source_object) return (1) end if exists (select * from sysobjects where name = 'sysmergearticles') begin if exists (select * from sysmergearticles where objid=@objid) select @is_for_merge=1 else select @is_for_merge=0 end else select @is_for_merge=0 -- PARSENAME VARS declare @UnqualName sysname --rightmost name node declare @QualName1 sysname -- END PARSENAME VARS select @UnqualName = PARSENAME(@source_object, 1) select @QualName1 = PARSENAME(@source_object, 2) if @UnqualName IS NULL return 1 if @QualName1 is not NULL select @owner = @QualName1 else select @owner=user_name(uid) from dbo.sysobjects where id = @objid select @tablename = @UnqualName select @qual_source_object = QUOTENAME(@owner) + N'.' + QUOTENAME(@tablename) select @at_publisher = 0 select @colid=colid from dbo.syscolumns where id=@objid and name=@column if @colid is NULL begin raiserror(21166, 16, -1, @column) return (1) end /* ** Considering holes, colid is not necessarily the one in bitmap. Get this value from count(*) */ select @missing_index = count(*) from dbo.syscolumns where id=@objid and colid<=@colid begin TRAN save tran sp_repldropcolumn if @is_for_merge=1 begin exec sp_replupdateschema @qual_source_object if @@ERROR<>0 goto FAILURE exec @retcode = sp_MSunmarkreplinfo @object=@tablename, @owner=@owner if @retcode<>0 or @@ERROR<>0 goto FAILURE --unmark this column so that it can be dropped update dbo.syscolumns set colstat=colstat & @merge_pub_unmarkcolumn_bit where id=@objid and colid = @colid if @@ERROR<>0 goto FAILURE end select @is_for_tran = 0 if exists (select * from dbo.sysobjects where name='sysarticles') begin if exists (select * from dbo.sysarticles where objid=@objid) begin if exists (SELECT P.pubid FROM dbo.syspublications P, dbo.sysarticles A, dbo.syssubscriptions S WHERE A.objid = @objid and A.pubid = P.pubid and A.artid = S.artid and (P.allow_sync_tran = 1 or P.allow_queued_tran = 1) and S.status = 2 -- active and S.sync_type != 2 -- not 'none' and S.update_mode != 0 ) -- not 'read only' and @force_reinit_subscription = 0 begin raiserror(21381, 16, -1, @tablename) goto FAILURE end select @is_for_tran =1 select pubid, artid, columns into #oldcols from sysarticles where objid = @objid end end /* ** First call TRAN Level stored procedure to */ if @is_for_tran = 1 begin exec @retcode = sp_MSprep_exclusive @qual_source_object if @@ERROR<>0 or @retcode <> 0 goto FAILURE exec @retcode = sp_replincrementlsn @schema_start_lsn OUTPUT if @@ERROR<>0 or @retcode <> 0 goto FAILURE exec @retcode = sp_replpostschema @objid if @@ERROR<>0 or @retcode <> 0 goto FAILURE declare #trancolumn CURSOR LOCAL FAST_FORWARD for select a.artid, p.name from sysarticles a, syspublications p where a.objid=@objid and p.pubid = a.pubid open #trancolumn fetch #trancolumn into @tran_artid, @tran_pubname while (@@fetch_status <> -1) BEGIN select @tran_artname=name from sysarticles where artid=@tran_artid exec @retcode = sp_articlecolumn @publication = @tran_pubname, @article = @tran_artname, @column = @column, @operation = 'drop', @change_active = 2 ,@force_invalidate_snapshot = 1 ,@force_reinit_subscription = 1 if @retcode <>0 or @@ERROR<>0 goto DROPTRAN fetch #trancolumn into @tran_artid, @tran_pubname END close #trancolumn deallocate #trancolumn end if not exists (select * from sysobjects where name='sysmergearticles') select @not_for_merge = 1 else if not exists (select * from sysmergearticles where objid=@objid) select @not_for_merge =1 if @not_for_merge = 1 begin if exists (select * from syscolumns where name=@column and id =@objid) begin exec ('alter table '+ @qual_source_object + ' drop column ' + @qual_column ) if @@ERROR<>0 goto FAILURE exec @retcode = sp_MSverifytranfilter @objid if @@ERROR <> 0 or @retcode <> 0 begin goto FAILURE end end end else begin if exists (select * from sysmergepublications where pubid in (select pubid from sysmergearticles where objid=@objid) and snapshot_ready=0) and exists (select * from syscolumns where name=@column and id =@objid) begin declare #nosnapshot CURSOR LOCAL FAST_FORWARD for select p.name, a.name from sysmergepublications p, sysmergearticles a where p.pubid=a.pubid and a.objid=@objid and p.snapshot_ready=0 open #nosnapshot fetch #nosnapshot into @pubname, @artname while (@@fetch_status<>-1) begin exec @retcode = sp_mergearticlecolumn @pubname, @artname, @column, 'drop', 'true' if @retcode <>0 or @@ERROR<>0 goto ERROR_EXIT fetch #nosnapshot into @pubname, @artname end close #nosnapshot deallocate #nosnapshot end declare #dropcolumn_schema CURSOR LOCAL FAST_FORWARD fast_forward for select name, pubid, artid, destination_owner, columns from sysmergearticles where objid=@objid and pubid in (select pubid from sysmergepublications where snapshot_ready>0) order by pubid ASC open #dropcolumn_schema fetch #dropcolumn_schema into @artname, @pubid, @artid, @dest_owner, @columnbm while (@@fetch_status <> -1) BEGIN if @dest_owner is not NULL select @dest_object = QUOTENAME(@dest_owner) + N'.' + QUOTENAME(@tablename) else select @dest_object = QUOTENAME(@tablename) exec @in_partition = sp_MStestbit @bm=@columnbm, @coltotest=@colid select @pubname=name, @publisher=publisher, @publisher_db=publisher_db from sysmergepublications where pubid=@pubid select @at_publisher=0 if @publisher=@@SERVERNAME and @publisher_db=db_name() and @in_partition<>0 begin select @at_publisher=1 select @schematext = 'exec sp_repldropcolumn ''' + @dest_object + ''', ''' + @column + ''', 1' select @schemaversion = schemaversion from sysmergeschemachange if (@schemaversion is NULL) set @schemaversion = 1 else select @schemaversion = 1 + max(schemaversion) from sysmergeschemachange set @schemaguid = newid() set @schematype = 11 /* alter table */ exec @retcode = sp_mergearticlecolumn @pubname, @artname, @column, 'drop', 'true' if @retcode<>0 or @@ERROR<>0 goto INNER_FAIL2 -- need to deallocate cursor for this loop. exec @retcode=sp_MSinsertschemachange @pubid, @artid, @schemaversion, @schemaguid, @schematype, @schematext if @@ERROR<>0 or @retcode<>0 goto INNER_FAIL2 select @schematext = 'alter table ' + @dest_object + ' drop column ' + @column select @schemaversion = @schemaversion + 1 set @schematype = 13 -- for Jet use only set @schemaguid = newid() exec @retcode=sp_MSinsertschemachange @pubid, @artid, @schemaversion, @schemaguid, @schematype, @schematext if @@ERROR<>0 or @retcode<>0 goto INNER_FAIL2 end fetch #dropcolumn_schema into @artname, @pubid, @artid, @dest_owner, @columnbm END close #dropcolumn_schema deallocate #dropcolumn_schema /* drop the column only once */ if exists (select * from syscolumns where id=@objid and name=@column) begin select @command = 'alter table ' + @qual_source_object + ' drop column ' + @qual_column exec (@command) if @@ERROR<>0 GOTO INNER_FAIL -- if transactionally replicated, verify that filter columns weren't dropped if( @is_for_tran = 1 ) begin exec @retcode = sp_MSverifytranfilter @objid if @@ERROR <> 0 or @retcode <> 0 begin goto FAILURE end end end declare #dropcolumn CURSOR LOCAL FAST_FORWARD fast_forward for select pubid, name, sync_objid, artid, missing_col_count, missing_cols, conflict_table, ins_conflict_proc from sysmergearticles where objid=@objid and pubid in (select pubid from sysmergepublications where snapshot_ready>0) order by pubid ASC open #dropcolumn fetch #dropcolumn into @pubid, @artname, @sync_objid, @artid, @missing_count, @missing_bm, @conflict_table, @ins_conflict_proc while (@@fetch_status <> -1) BEGIN select @pubname=name, @publisher=publisher, @publisher_db=publisher_db from sysmergepublications where pubid=@pubid select @at_publisher=0 if @publisher=@@SERVERNAME and @publisher_db=db_name() select @at_publisher=1 if @conflict_table is not NULL begin select @con_id = object_id(@conflict_table) if @con_id is NULL begin raiserror(21286, 16, -1, @conflict_table) GOTO INNER_FAIL end select @colid=colid from syscolumns where id = @con_id and name=@column if exists (select name from syscolumns where name=@column and id=@con_id) begin select @command = 'alter table ' + QUOTENAME(@conflict_table) + ' drop column ' + @qual_column exec (@command) if @@ERROR<>0 goto INNER_FAIL end end /* ** Force the re-generation of conflict insert table cause the schema is changed for sure */ if @ins_conflict_proc is not NULL and object_id(@ins_conflict_proc) is not NULL begin exec ('drop procedure ' + @ins_conflict_proc) if @@ERROR<>0 goto INNER_FAIL update sysmergearticles set ins_conflict_proc=NULL where pubid=@pubid and artid=@artid if @@ERROR<>0 goto INNER_FAIL end if @at_publisher=1 begin exec @retcode = sp_MSpublicationview @pubname, 1 if @retcode<>0 or @@ERROR<>0 begin raiserror(21201, 16, -1) goto INNER_FAIL end end select @missing_count=@missing_count + 1 select @old_missing_bm=@missing_bm exec @retcode=sp_MSsetbit @missing_bm OUTPUT, @missing_index if @retcode<>0 or @@ERROR<>0 goto INNER_FAIL --if no change, that is, the column is already marked as missing, do not increase --its count if @missing_bm<>@old_missing_bm begin update sysmergearticles set missing_col_count=@missing_count, missing_cols=@missing_bm where pubid=@pubid and artid=@artid if @@ERROR<>0 goto INNER_FAIL end exec @retcode = sp_MSdroparticletriggers @qual_source_object if @retcode<>0 or @@ERROR<>0 goto INNER_FAIL exec @retcode = sp_MSaddmergetriggers @qual_source_object if @retcode<>0 or @@ERROR<>0 goto INNER_FAIL exec @retcode = sp_MSsetartprocs @publication=@pubname, @article=@artname, @force_flag=1 if @retcode<>0 or @@ERROR<>0 goto INNER_FAIL /* ** passing in one more parameter to sp_MSgetconflictinsertproc such that there is ** no select statement at the end of that SP as needed else where. The default is 1. */ exec @retcode = sp_MSgetconflictinsertproc @artid, @pubid, 0 if @retcode<>0 or @@ERROR<>0 goto INNER_FAIL fetch #dropcolumn into @pubid, @artname, @sync_objid, @artid, @missing_count, @missing_bm, @conflict_table, @ins_conflict_proc END CLOSE #dropcolumn DEALLOCATE #dropcolumn if @is_for_merge=1 begin exec @retcode = sp_MSmarkreplinfo @tablename, @owner if @retcode<>0 or @@ERROR<>0 goto FAILURE end end -- finally, if it's transactional, trigger a reinit if @is_for_tran = 1 begin if exists (select * from sysarticles where objid = @objid) begin declare #trancolumn CURSOR LOCAL FAST_FORWARD for select a.artid, p.name from sysarticles a, syspublications p, #oldcols oc where a.objid=@objid and p.pubid = a.pubid and oc.artid = a.artid and oc.columns <> a.columns open #trancolumn fetch #trancolumn into @tran_artid, @tran_pubname while (@@fetch_status <> -1) BEGIN select @tran_artname=name, @tran_pubid = pubid, @owner = dest_owner, @tablename = dest_table from sysarticles where artid=@tran_artid if(@force_reinit_subscription = 0) begin if(@owner is not NULL) and (len(@owner) > 0) select @qual_dest_object = QUOTENAME(@owner) + N'.' else select @qual_dest_object = N'' if(@tablename is not null) and (len(@tablename) > 0) select @qual_dest_object = @qual_dest_object + QUOTENAME(@tablename) else select @qual_dest_object = @qual_source_object exec @retcode = sp_MSrepl_schema @pubname = @tran_pubname ,@artid = @tran_artid ,@qual_source_object = @qual_dest_object ,@column = @column ,@operation = 1 -- 0 is add, 1 is delete ,@schema_change_script = @schema_change_script if @retcode <>0 or @@ERROR<>0 goto DROPTRAN end exec @retcode = dbo.sp_MSreinit_article @publication = @tran_pubname ,@article = @tran_artname ,@need_new_snapshot = @force_invalidate_snapshot ,@need_reinit_subscription = @force_reinit_subscription ,@force_invalidate_snapshot = @force_invalidate_snapshot ,@force_reinit_subscription = @force_reinit_subscription if @retcode <>0 or @@ERROR<>0 goto DROPTRAN fetch #trancolumn into @tran_artid, @tran_pubname END close #trancolumn deallocate #trancolumn exec @retcode = sp_replincrementlsn @schema_end_lsn OUTPUT if @@ERROR<>0 or @retcode <> 0 goto FAILURE if (@schema_start_lsn is not null) and (@schema_end_lsn is not null) begin insert systranschemas (tabid, startlsn, endlsn) values (@objid, @schema_start_lsn, @schema_end_lsn) if @@ERROR<>0 goto FAILURE exec @retcode = sp_replflush @objid, @schema_start_lsn, @schema_end_lsn if @@ERROR<>0 or @retcode <> 0 goto FAILURE end else goto FAILURE end end COMMIT TRAN return (0) DROPTRAN: CLOSE #trancolumn DEALLOCATE #trancolumn GOTO FAILURE INNER_FAIL: CLOSE #dropcolumn DEALLOCATE #dropcolumn GOTO FAILURE INNER_FAIL2: CLOSE #dropcolumn_schema DEALLOCATE #dropcolumn_schema GOTO FAILURE ERROR_EXIT: CLOSE #nosnapshot DEALLOCATE #nosnapshot FAILURE: rollback tran sp_repldropcolumn commit tran raiserror(21284, 16, -1, @column, @source_object) return (1) go exec dbo.sp_MS_marksystemobject sp_repldropcolumn go grant execute on dbo.sp_repldropcolumn to public go raiserror('Creating procedure sp_repladdcolumn', 0,1) GO CREATE PROCEDURE sp_repladdcolumn( @source_object nvarchar (358), @column sysname, @typetext nvarchar(3000), @publication_to_add nvarchar(4000) = 'all', @from_agent int = 0, @schema_change_script nvarchar(4000) = NULL, @force_invalidate_snapshot bit = 1, /* Force invalidate existing snapshot */ @force_reinit_subscription bit = 0 /* Force reinit subscription */ ) as set nocount on declare @objid int declare @pubid uniqueidentifier declare @retcode int declare @partitioned int declare @at_publisher bit declare @pubname sysname declare @artname sysname declare @colid int declare @tablename sysname declare @artid uniqueidentifier declare @tran_artid int declare @tran_pubid int declare @schematext nvarchar(4000) declare @schemaversion int declare @schematype int declare @schemaguid uniqueidentifier declare @conflict_table sysname declare @ins_conflict_proc sysname declare @publisher sysname declare @qual_column nvarchar(140) declare @not_for_merge int declare @publisher_db sysname declare @command nvarchar(3000) declare @sync_objid int declare @con_id int declare @owner sysname declare @dest_owner sysname declare @dest_object nvarchar(386) declare @merge_pub_object_bit int declare @is_for_merge bit declare @is_for_tran bit declare @dbname sysname declare @servername sysname declare @no_publication bit declare @no_schema_replication bit declare @qual_source_object nvarchar(362) declare @len int declare @prec int declare @scale int declare @typename nvarchar(270) declare @qual_dest_object nvarchar(362) declare @invalid_datatype bit declare @is_identity_or_timestamp bit declare @xtype int declare @iscomputed bit declare @pass_to_heterogenious bit declare @merge_pub_markcolumn_bit int declare @schema_start_lsn binary(10) declare @schema_end_lsn binary(10) declare @nickname int declare @columns_in_partition int /* ** Security Check */ EXEC @retcode = dbo.sp_MSreplcheck_publish IF @@ERROR <> 0 or @retcode <> 0 return (1) select @qual_column=QUOTENAME(@column) select @merge_pub_markcolumn_bit = 0x4000 select @objid = object_id(@source_object) -- check to see if this stored procedure is called via replication agent. if sessionproperty('replication_agent')<>1 select @from_agent = 0 else begin --if table does not exists and the SP is called from replication agent, ignore the error and exit with success. select @from_agent = 1 if @objid is NULL return (0) end if @objid is NULL begin raiserror(14027, 16, -1, @source_object) return (1) end if exists (select * from syscolumns where id=@objid and name=@column) begin if @from_agent=0 begin raiserror(21255, 16, -1, @column, @source_object) return (1) end else return (0) end -- PARSENAME VARS declare @UnqualName sysname --rightmost name node declare @QualName1 sysname -- END PARSENAME VARS select @UnqualName = PARSENAME(@source_object, 1) select @QualName1 = PARSENAME(@source_object, 2) if @UnqualName IS NULL return 1 if @QualName1 is not NULL select @owner = @QualName1 else select @owner=user_name(uid) from sysobjects where id = @objid select @tablename = @UnqualName select @qual_source_object = QUOTENAME(@owner) + '.' + QUOTENAME(@tablename) select @no_schema_replication = 0 select @no_publication=0 select @servername=@@SERVERNAME select @dbname=db_name() select @merge_pub_object_bit = 128 select @not_for_merge = 0 if exists (select * from sysobjects where name='sysmergearticles') begin if @from_agent=0 and exists (select * from sysmergearticles where objid=@objid and pubid not in (select pubid from sysmergepublications where LOWER(publisher)=LOWER(@servername) and publisher_db=@dbname)) begin raiserror(21260, 16, -1, @dbname, @servername, @source_object) return (1) end end select @invalid_datatype=0 /* the transaction below is just an experiment to validate type text */ BEGIN TRAN SAVE TRANSACTION fake_move exec @retcode = sp_MSunmarkreplinfo @object=@tablename, @owner=@owner if @retcode<>0 or @@ERROR<>0 begin goto CHECKING_DONE end declare @temp_id int declare @temp_colid int select @is_identity_or_timestamp = 0 exec ('alter table ' + @qual_source_object + ' add ' + @qual_column + ' ' + @typetext) select @temp_id = object_id(@qual_source_object) if @temp_id is NULL begin raiserror(21285, 16, -1, @column, @source_object) select @invalid_datatype = 1 GOTO CHECKING_DONE end select @pass_to_heterogenious=0, @temp_colid = colid, @xtype=xtype, @iscomputed=iscomputed from syscolumns where id = @temp_id and name=@column if @iscomputed <> 1 and type_name(@xtype) <> 'timestamp' select @pass_to_heterogenious=1 if COLUMNPROPERTY(@temp_id, @column, 'IsIdentity') = 1 or type_name(@xtype) = 'timestamp' select @is_identity_or_timestamp = 1 if COLUMNPROPERTY(@temp_id, @column, 'IsIdentity') = 0 and not exists (select * from syscolumns where id = @temp_id and name=@column and isnullable=1) and not exists (select * from sysconstraints where id=@temp_id and colid=@temp_colid and status & 5 = 5) and @iscomputed <> 1 and type_name(@xtype) <> 'timestamp' --not computed column nor timestamp column begin select @invalid_datatype = 1 end CHECKING_DONE: ROLLBACK TRANSACTION fake_move COMMIT TRAN if @invalid_datatype = 1 begin raiserror(21285, 16, -1, @column, @source_object) return (1) end if exists (select * from sysobjects where id=@objid and replinfo & @merge_pub_object_bit <>0) select @is_for_merge = 1 else select @is_for_merge = 0 select @is_for_tran = 0 if not exists (select * from sysobjects where name='sysmergepublications') and not exists (select * from sysobjects where name='syspublications') begin raiserror(21230, 16, -1) return (1) end create table #tmp_table (name sysname collate database_default) if LOWER(@publication_to_add)='all' or LOWER(@publication_to_add)='[all]' begin select @publication_to_add = '%' end else begin if charindex(',', @publication_to_add)<>0 --publication list begin declare @tmp_publist nvarchar(4000) declare @total int declare @invalid_pub sysname select @invalid_pub = NULL select @tmp_publist = @publication_to_add while @tmp_publist <> '' begin select @tmp_publist = LTRIM(@tmp_publist) select @total=len(@tmp_publist) select @len=charindex(',', @tmp_publist) if @len=0 begin insert #tmp_table values(@tmp_publist) select @tmp_publist='' end else begin insert #tmp_table values(substring(@tmp_publist, 1, @len-1)) select @tmp_publist = right(@tmp_publist, @total-@len) end end if exists (select * from sysobjects where name='sysmergepublications') and exists (select * from sysobjects where name='syspublications') select @invalid_pub=name from #tmp_table where name not in (select ('[' + name + ']') from sysmergepublications) and name not in (select ('[' + name + ']') from syspublications) else if exists (select * from sysobjects where name='sysmergepublications') select @invalid_pub=name from #tmp_table where name not in (select ('[' + name + ']') from sysmergepublications) else if exists (select * from sysobjects where name='syspublications') select @invalid_pub=name from #tmp_table where name not in (select ('[' + name + ']') from syspublications) if @invalid_pub is not NULL and @from_agent=0 begin raiserror(21274, 16, -1, @invalid_pub) return (1) end end else begin --single publication insert #tmp_table values(@publication_to_add) insert #tmp_table values('[' + @publication_to_add + ']') end end -- if not for TRAN, it has to be a merge publication if not exists (select * from sysobjects where name='syspublications') begin if not exists (select * from sysmergepublications where name like @publication_to_add or (('[' + name + ']') in (select name from #tmp_table))) select @no_publication = 1 if not exists (select * from sysmergearticles where objid=@objid and pubid in (select pubid from sysmergepublications where name like @publication_to_add or (('[' + name + ']') in (select name from #tmp_table)))) select @no_schema_replication = 1 end -- if not for merge, it has to be a tran publication if not exists (select * from sysobjects where name='sysmergepublications') begin if not exists (select * from syspublications where name like @publication_to_add or (('[' + name + ']') in (select name from #tmp_table))) select @no_publication = 1 if not exists (select * from sysarticles where objid=@objid and pubid in (select pubid from syspublications where name like @publication_to_add or (('[' + name + ']') in (select name from #tmp_table)))) select @no_schema_replication =1 end if exists (select * from sysobjects where name='sysmergepublications') and exists (select * from sysobjects where name='syspublications') begin if not exists (select * from syspublications where name like @publication_to_add or (('[' + name + ']') in (select name from #tmp_table))) and not exists (select * from sysmergepublications where name like @publication_to_add or (('[' + name + ']') in (select name from #tmp_table))) select @no_publication = 1 if not exists (select * from sysarticles where objid=@objid and pubid in (select pubid from syspublications where name like @publication_to_add or (('[' + name + ']') in (select name from #tmp_table)))) and not exists (select * from sysmergearticles where objid=@objid and pubid in (select pubid from sysmergepublications where name like @publication_to_add or (('[' + name + ']') in (select name from #tmp_table)))) select @no_schema_replication=1 end if @no_publication=1 and @publication_to_add <> '%' and LOWER(@publication_to_add)<>'none' and LOWER(@publication_to_add)<>'[none]' begin raiserror(21200, 16, -1, @publication_to_add) return (1) end if @no_schema_replication=1 and LOWER(@publication_to_add)<>'none' and LOWER(@publication_to_add)<>'[none]' begin if @publication_to_add = '%' begin raiserror(21246, 16, -1, @source_object) return (1) end else begin raiserror(21245, 16, -1, @source_object, @publication_to_add) return (1) end end select @at_publisher = 0 if exists (select * from sysobjects where name = 'sysarticles') begin if exists (select a.objid from sysarticles a, syspublications p where a.objid=@objid and p.pubid = a.pubid and (p.name like @publication_to_add or charindex('[' + p.name + ']', @publication_to_add)>0)) begin select @is_for_tran = 1 end end if (@is_for_tran =1 and @force_reinit_subscription = 0) begin if (@is_identity_or_timestamp = 1 ) begin raiserror(21380, 16, -1) return (1) end if exists (SELECT P.pubid FROM dbo.syspublications P, dbo.sysarticles A, dbo.syssubscriptions S WHERE A.objid = @objid and A.pubid = P.pubid and A.artid = S.artid and (P.allow_sync_tran = 1 or P.allow_queued_tran = 1) and S.status = 2 -- active and S.sync_type != 2 -- not 'none' and S.update_mode != 0 ) -- not 'read only' begin raiserror(21381, 16, -1, @tablename) return (1) end end begin TRAN save tran sp_repladdcolumn if @is_for_merge=1 begin exec sp_replupdateschema @qual_source_object if @@ERROR<>0 goto FAILURE exec @retcode = sp_MSunmarkreplinfo @object=@tablename, @owner=@owner if @retcode<>0 or @@ERROR<>0 goto FAILURE end if not exists (select * from sysobjects where name='sysmergearticles') select @not_for_merge = 1 else if not exists (select * from sysmergearticles where objid=@objid) select @not_for_merge =1 if @is_for_tran = 1 begin if not exists (select * from syscolumns where name=@column and id =@objid) begin exec @retcode = sp_MSprep_exclusive @qual_source_object if @@ERROR<>0 or @retcode <> 0 goto FAILURE exec @retcode = sp_replincrementlsn @schema_start_lsn OUTPUT if @@ERROR<>0 or @retcode <> 0 goto FAILURE exec @retcode = sp_replpostschema @objid if @@ERROR<>0 or @retcode <> 0 goto FAILURE exec ('alter table '+ @qual_source_object + ' add ' + @qual_column + ' ' + @typetext ) if @@ERROR<>0 goto FAILURE end end if @not_for_merge = 0 begin if not exists (select * from syscolumns where name=@column and id =@objid) begin exec ('alter table '+ @qual_source_object + ' add ' + @qual_column + ' ' + @typetext ) if @@ERROR<>0 goto FAILURE end /* ** whether the column is added to this publication, the articles whose underlying table contains ** a new column will be regareded as vertically partitioned. */ update sysmergearticles set vertical_partition=1 where objid=@objid if @@ERROR<>0 goto FAILURE /* ** Heterogenious subscriber are not to receive computed column or timestamp columns */ declare #nosnapshot CURSOR LOCAL FAST_FORWARD for select p.name, a.name, a.pubid from sysmergepublications p, sysmergearticles a where p.pubid=a.pubid and a.objid=@objid and p.snapshot_ready=0 and (p.name like @publication_to_add or charindex('[' + p.name + ']', @publication_to_add)>0) and (p.sync_mode=0 or @pass_to_heterogenious=1) open #nosnapshot fetch #nosnapshot into @pubname, @artname, @pubid while (@@fetch_status<>-1) begin exec @retcode = sp_mergearticlecolumn @pubname, @artname, @column, 'add', 'true' if @retcode <>0 or @@ERROR<>0 goto ERROR_EXIT fetch #nosnapshot into @pubname, @artname, @pubid end CLOSE #nosnapshot DEALLOCATE #nosnapshot /* ** Handle those cases where snapshot is already ran and new schema change needs to be added ** ; Heterogenious subscriber are not to receive computed column or timestamp columns */ declare #addcolumn CURSOR LOCAL FAST_FORWARD fast_forward for select pubid, name, sync_objid, artid, conflict_table, ins_conflict_proc, destination_owner from sysmergearticles where objid=@objid and pubid in (select pubid from sysmergepublications where snapshot_ready>0 and (sync_mode=0 or @pass_to_heterogenious=1)) open #addcolumn fetch #addcolumn into @pubid, @artname, @sync_objid, @artid, @conflict_table, @ins_conflict_proc, @dest_owner while (@@fetch_status <> -1) BEGIN if @dest_owner is not NULL select @dest_object = QUOTENAME(@dest_owner) + '.' + QUOTENAME(@tablename) else select @dest_object = QUOTENAME(@tablename) select @pubname=name, @publisher=publisher, @publisher_db=publisher_db from sysmergepublications where pubid=@pubid if @conflict_table is not NULL begin select @con_id = object_id(@conflict_table) if @con_id is NULL begin raiserror(21286, 16, -1, @conflict_table) GOTO INNER_FAIL end if not exists (select name from syscolumns where name=@column and id=@con_id) and (@pubname like @publication_to_add or charindex('[' + @pubname + ']', @publication_to_add)>0) begin select @typename = type_name(xtype), @len = length, @prec = COLUMNPROPERTY(id, name, 'precision'), @scale = scale, @iscomputed=iscomputed, @xtype=xtype from syscolumns where name=@column and id=@objid --we want to column property of 'computed' or 'timestamp' of the newly added column if @iscomputed <> 1 and type_name(@xtype) <> 'timestamp' begin if @typename='nvarchar' or @typename='nchar' -- a unit of nchar takes 2 bytes select @len = @len/2 exec @retcode = dbo.sp_MSmaptype @typename out, @len, @prec, @scale if @@error<>0 OR @retcode <>0 GOTO INNER_FAIL --doing so instead of using @typetext as we once did is that we do not want any constraint or identity properties --defined on conflict tables. Also it is safe to make the column NULLable in conflict tables. select @command = 'alter table ' + QUOTENAME(@conflict_table) + ' add ' + @qual_column + ' ' + @typename + ' NULL ' end else --continue to use typetext when adding computed/timestamp column to the conflict tables. begin select @command = 'alter table ' + QUOTENAME(@conflict_table) + ' add ' + @qual_column + ' ' + @typetext end exec (@command) if @@ERROR<>0 goto INNER_FAIL end end /* ** Force the re-generation of conflict insert table cause the schema is changed for sure */ if @ins_conflict_proc is not NULL and object_id(@ins_conflict_proc) is not NULL and (@pubname like @publication_to_add or charindex('[' + @pubname + ']', @publication_to_add)>0) begin exec ('drop procedure ' + @ins_conflict_proc) if @@ERROR<>0 goto INNER_FAIL update sysmergearticles set ins_conflict_proc=NULL where pubid=@pubid and artid=@artid if @@ERROR<>0 goto INNER_FAIL end /* ** Force the regeneration of publication view for all publications that publish the current table. */ update sysmergearticles set vertical_partition=1 where artid=@artid and pubid=@pubid if @@ERROR<>0 goto INNER_FAIL select @at_publisher=0 if @publisher=@@SERVERNAME and @publisher_db=db_name() begin select @at_publisher=1 if @pubname like @publication_to_add or charindex('[' + @pubname + ']', @publication_to_add)>0 begin select @schematext = 'exec sp_repladdcolumn ''' + @dest_object + ''',''' + @column + ''','+ QUOTENAME(@typetext) + ', ''' + @publication_to_add + ''', 1' select @schemaversion = schemaversion from sysmergeschemachange if (@schemaversion is NULL) set @schemaversion = 1 else select @schemaversion = 1 + max(schemaversion) from sysmergeschemachange set @schemaguid = newid() set @schematype = 11 /* alter table */ exec @retcode = sp_mergearticlecolumn @pubname, @artname, @column, 'add','true' if @retcode<>0 or @@ERROR<>0 goto INNER_FAIL -- need to deallocate cursor for this loop. exec @retcode=sp_MSinsertschemachange @pubid, @artid, @schemaversion, @schemaguid, @schematype, @schematext if @@ERROR<>0 or @retcode<>0 goto INNER_FAIL --insert a schema change for Jet specifically subscribers select @schematext = 'alter table ' + @dest_object + ' add ' + @column + ' ' + @typetext select @schemaversion = @schemaversion + 1 set @schematype = 13 -- for Jet use only set @schemaguid = newid() exec @retcode=sp_MSinsertschemachange @pubid, @artid, @schemaversion, @schemaguid, @schematype, @schematext if @@ERROR<>0 or @retcode<>0 goto INNER_FAIL end end if @at_publisher=1 begin exec @retcode = sp_MSpublicationview @pubname, 1 if @retcode<>0 or @@ERROR<>0 goto INNER_FAIL end select @columns_in_partition=count(*) from syscolumns where id = @sync_objid if @columns_in_partition>246 begin raiserror('Failed to add column ''%s'' to table ''%s'' because there are too many columns in the partition', 16, -1,@column, @source_object) goto INNER_FAIL end exec @retcode = sp_MSdroparticletriggers @qual_source_object if @retcode<>0 or @@ERROR<>0 goto INNER_FAIL exec @retcode = sp_MSaddmergetriggers @qual_source_object if @retcode<>0 or @@ERROR<>0 goto INNER_FAIL /* ** Force the regeneration of merge procs for all publications that publish the current table */ exec @retcode = sp_MSsetartprocs @publication=@pubname, @article=@artname, @force_flag=1 if @retcode<>0 or @@ERROR<>0 goto INNER_FAIL /* ** passing in one more parameter to sp_MSgetconflictinsertproc such that there is ** no select statement at the end of that SP as needed else where. The default is 1. */ exec @retcode = sp_MSgetconflictinsertproc @artid, @pubid, 0 if @retcode<>0 or @@ERROR<>0 goto INNER_FAIL fetch #addcolumn into @pubid, @artname, @sync_objid, @artid, @conflict_table, @ins_conflict_proc, @dest_owner END close #addcolumn deallocate #addcolumn declare @column_tracking int select @column_tracking=column_tracking, @nickname=nickname from sysmergearticles where objid=@objid if @column_tracking = 1 begin --make sure there is no colv overflow, which was not caught by 246 column restriction because --users keep adding/dropping column, which causes no increase in number of coumns but consume --colv slot cause we never release the slot when a column is dropped if exists (select * from MSmerge_contents where tablenick=@nickname and len(colv1)>2040) begin raiserror(21418, 16, -1,@column, @source_object) goto INNER_FAIL end --apend an lineage slot for the new column. update MSmerge_contents set colv1=substring(colv1, 1, (datalength(colv1)-1)) + substring(colv1, 1, 4) + 0x01000000FF where tablenick=@nickname if @@ERROR<>0 goto FAILURE end end if @is_for_tran = 1 begin declare #trancolumn CURSOR LOCAL FAST_FORWARD for select a.artid, p.name from sysarticles a, syspublications p where a.objid=@objid and p.pubid = a.pubid and (p.name like @publication_to_add or charindex('[' + p.name + ']', @publication_to_add)>0) open #trancolumn fetch #trancolumn into @tran_artid, @pubname while (@@fetch_status <> -1) BEGIN select @artname = name, @tran_pubid = pubid, @owner = dest_owner, @tablename = dest_table from sysarticles where artid=@tran_artid exec @retcode = sp_articlecolumn @publication = @pubname, @article = @artname, @column = @column, @operation = 'add', @change_active = 2 ,@force_invalidate_snapshot = 1 ,@force_reinit_subscription = 1 if @retcode <>0 or @@ERROR<>0 goto DROPTRAN if(@force_reinit_subscription = 0) begin if(@owner is not NULL) and (len(@owner) > 0) select @qual_dest_object = QUOTENAME(@owner) + N'.' else select @qual_dest_object = N'' if(@tablename is not null) and (len(@tablename) > 0) select @qual_dest_object = @qual_dest_object + QUOTENAME(@tablename) else select @qual_dest_object = @qual_source_object exec @retcode = sp_MSrepl_schema @pubname = @pubname ,@artid = @tran_artid ,@qual_source_object = @qual_dest_object ,@column = @column ,@operation = 0 -- 0 is add, 1 is delete ,@typetext = @typetext ,@schema_change_script = @schema_change_script if @retcode <>0 or @@ERROR<>0 goto DROPTRAN end exec @retcode = dbo.sp_MSreinit_article @publication = @pubname ,@article = @artname ,@need_new_snapshot = @force_invalidate_snapshot ,@need_reinit_subscription = @force_reinit_subscription ,@force_invalidate_snapshot = @force_invalidate_snapshot ,@force_reinit_subscription = @force_reinit_subscription if @retcode <>0 or @@ERROR<>0 goto DROPTRAN fetch #trancolumn into @tran_artid, @pubname END close #trancolumn deallocate #trancolumn exec @retcode = sp_replincrementlsn @schema_end_lsn OUTPUT if @@ERROR<>0 or @retcode <> 0 goto FAILURE if (@schema_start_lsn is not null) and (@schema_end_lsn is not null) begin insert systranschemas (tabid, startlsn, endlsn) values (@objid, @schema_start_lsn, @schema_end_lsn) if @@ERROR<>0 goto FAILURE exec @retcode = sp_replflush @objid, @schema_start_lsn, @schema_end_lsn if @@ERROR<>0 or @retcode <> 0 goto FAILURE end else goto FAILURE end /* Get back to its original replication state */ if @is_for_merge=1 begin exec @retcode = sp_MSmarkreplinfo @tablename, @owner if @retcode<>0 or @@ERROR<>0 goto FAILURE update syscolumns set colstat = colstat | @merge_pub_markcolumn_bit where id=@objid and name= @column if @@ERROR<>0 goto FAILURE end COMMIT TRAN return (0) INNER_FAIL: CLOSE #addcolumn DEALLOCATE #addcolumn GOTO FAILURE ERROR_EXIT: CLOSE #nosnapshot DEALLOCATE #nosnapshot GOTO FAILURE DROPTRAN: CLOSE #trancolumn DEALLOCATE #trancolumn FAILURE: rollback tran sp_repladdcolumn commit tran raiserror(21285, 16, -1, @column, @source_object) return (1) go exec dbo.sp_MS_marksystemobject sp_repladdcolumn go grant execute on dbo.sp_repladdcolumn to public go EXEC dbo.sp_MS_marksystemobject sp_MSget_jobstate GO exec dbo.sp_MS_marksystemobject sp_MSunc_to_drive go exec dbo.sp_MS_marksystemobject sp_MSrepl_isdbowner go dump tran master with no_log go raiserror('Creating procedure sp_MSagent_access_check',0,1) go CREATE PROCEDURE sp_MSagent_access_check ( @job_id VARBINARY(16), @agent_type sysname = NULL -- 'distribution' or 'merge', case insensitive ) AS DECLARE @retcode int DECLARE @count int IF @agent_type IS NOT NULL BEGIN IF LOWER(@agent_type collate SQL_Latin1_General_CP1_CS_AS) NOT IN (N'distribution', N'merge') BEGIN RAISERROR(21170, 16, -1) RETURN (1) END END SELECT @retcode = 0 -- Create a list of owners of the subscriptions depending on the given -- agent CREATE TABLE #sub_owner_list (owner_name sysname collate database_default) -- Try querying the Transactional subscriptions for the owner IF @agent_type IS NULL OR LOWER(@agent_type collate SQL_Latin1_General_CP1_CS_AS) = N'distribution' BEGIN IF EXISTS (SELECT * FROM sysobjects WHERE type in ('U', 'S') AND name = N'syssubscriptions') BEGIN INSERT INTO #sub_owner_list SELECT DISTINCT login_name FROM dbo.syssubscriptions WHERE distribution_jobid = @job_id END IF NOT EXISTS (SELECT * FROM #sub_owner_list) AND @agent_type IS NOT NULL BEGIN RAISERROR(21167, 16, -1, 'Distribution') SELECT @retcode = 1 GOTO FAILURE END END IF (@agent_type IS NULL AND NOT EXISTS (SELECT * FROM #sub_owner_list)) OR LOWER(@agent_type collate SQL_Latin1_General_CP1_CS_AS) = N'merge' BEGIN SELECT @count = COUNT(*) FROM sysobjects WHERE name IN (N'sysmergesubscriptions', N'MSmerge_replinfo') IF @count = 2 BEGIN INSERT INTO #sub_owner_list SELECT DISTINCT sms.login_name FROM dbo.MSmerge_replinfo mr INNER JOIN dbo.sysmergesubscriptions sms ON mr.repid = sms.subid WHERE mr.merge_jobid = @job_id END IF NOT EXISTS (SELECT * FROM #sub_owner_list) AND @agent_type IS NOT NULL BEGIN RAISERROR(21167, 16, -1, 'Merge') SELECT @retcode = 1 GOTO FAILURE END END IF NOT EXISTS (SELECT * FROM #sub_owner_list) BEGIN RAISERROR(21134, 16, -1) SELECT @retcode = 1 GOTO FAILURE END IF suser_sname(suser_sid()) NOT IN (SELECT owner_name FROM #sub_owner_list) AND is_srvrolemember('sysadmin') <> 1 AND is_member('db_owner') <> 1 BEGIN RAISERROR(21168, 16, -1) SELECT @retcode = 1 GOTO FAILURE END FAILURE: DROP TABLE #sub_owner_list RETURN @retcode GO EXEC dbo.sp_MS_marksystemobject sp_MSagent_access_check GO raiserror('Creating procedure sp_enableagentoffload',0,1) go CREATE PROCEDURE sp_enableagentoffload ( @job_id VARBINARY(16), @offloadserver sysname = NULL, @agent_type sysname = NULL -- 'distribution' or 'merge', case insensitive ) AS SET NOCOUNT ON DECLARE @retcode INT DECLARE @distributor sysname DECLARE @distributiondb sysname DECLARE @distproc NVARCHAR(300) SELECT @retcode = 0 SELECT @distributor = NULL SELECT @distributiondb = NULL EXEC @retcode = sp_MSreplcheckoffloadserver @offloadserver IF @retcode<>0 OR @@error<>0 RETURN (1) EXEC @retcode = sp_MSagent_access_check @job_id = @job_id, @agent_type = @agent_type IF @retcode <> 0 RETURN @retcode EXEC @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT, @distribdb = @distributiondb OUTPUT IF @retcode <> 0 RETURN @retcode SELECT @distributor = RTRIM(@distributor) IF LOWER(@@SERVERNAME) <> LOWER(@distributor) BEGIN SELECT @distproc = @distributor + '.' + @distributiondb + '.dbo.sp_MSenableagentoffload' END ELSE BEGIN SELECT @distproc = @distributiondb + '.dbo.sp_MSenableagentoffload' END EXECUTE @retcode = @distproc @job_id = @job_id, @offloadserver = @offloadserver RETURN @retcode GO EXEC dbo.sp_MS_marksystemobject sp_enableagentoffload GO print '' print 'Creating procedure sp_disableagentoffload' go CREATE PROCEDURE sp_disableagentoffload ( @job_id VARBINARY(16), @offloadserver sysname = NULL, @agent_type sysname = NULL -- 'distribution' or 'merge', case insensitive ) AS SET NOCOUNT ON DECLARE @retcode INT DECLARE @distributor sysname DECLARE @distributiondb sysname DECLARE @distproc NVARCHAR(300) SELECT @retcode = 0 SELECT @distributor = NULL SELECT @distributiondb = NULL EXEC @retcode = sp_MSagent_access_check @job_id = @job_id, @agent_type = @agent_type IF @retcode <> 0 RETURN @retcode EXEC @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT, @distribdb = @distributiondb OUTPUT IF @retcode <> 0 RETURN @retcode SELECT @distributor = RTRIM(@distributor) IF LOWER(@@SERVERNAME) <> LOWER(@distributor) BEGIN SELECT @distproc = @distributor + '.' + @distributiondb + '.dbo.sp_MSdisableagentoffload' END ELSE BEGIN SELECT @distproc = @distributiondb + '.dbo.sp_MSdisableagentoffload' END EXECUTE @retcode = @distproc @job_id = @job_id, @offloadserver = @offloadserver RETURN @retcode GO EXEC dbo.sp_MS_marksystemobject sp_disableagentoffload GO print '' print 'Creating procedure sp_getagentoffloadinfo' go CREATE PROCEDURE sp_getagentoffloadinfo ( @job_id VARBINARY(16) ) AS SET NOCOUNT ON DECLARE @retcode INT DECLARE @distributor sysname DECLARE @distributiondb sysname DECLARE @distproc NVARCHAR(300) SELECT @retcode = 0 SELECT @distributor = NULL SELECT @distributiondb = NULL -- security check, db_owner EXEC @retcode = dbo.sp_MSreplcheck_publish IF @@ERROR <> 0 or @retcode <> 0 return (1) EXEC @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT, @distribdb = @distributiondb OUTPUT IF @retcode <> 0 RETURN @retcode SELECT @distributor = RTRIM(@distributor) SELECT @distproc = @distributor + '.' + @distributiondb + '.dbo.sp_MSgetagentoffloadinfo' EXECUTE @retcode = @distproc @job_id = @job_id RETURN @retcode GO EXEC dbo.sp_MS_marksystemobject sp_getagentoffloadinfo GO print '' print 'Creating procedure sp_copysubscription' go CREATE PROCEDURE sp_copysubscription ( @filename nvarchar(260), @temp_dir nvarchar(260) = NULL, -- Directory contains temp files. If not specified, SQL -- server default data directory will be used. @overwrite_existing_file bit = 0 ) AS SET NOCOUNT ON /* ** Declarations. */ declare @cmd nvarchar(4000) declare @retcode int declare @data_path nvarchar(260) declare @subscriber_srvid int declare @subscriber_db sysname declare @backup_path nvarchar(260) declare @temp_data_path nvarchar(260) declare @temp_log_path nvarchar(260) declare @retention int declare @retention_date datetime declare @pubid uniqueidentifier /* * Initializations */ select @retcode = 0 select @subscriber_srvid = 0 select @subscriber_db = db_name() -- We only support single file attach. Check to make sure -- there are only 2 files, one data file and one log file if (select count(*) from sysfiles) > 2 begin raiserror(21212,16, -1) return 1 end /* Make sure all tran sub allows attach */ declare @publication sysname declare @publisher sysname declare @tran_found bit declare @merge_found bit select @tran_found = 0 select @merge_found = 0 /* ** Make sure all merge subscriptions in the current database ** have allow_subscription_copy set to TRUE ** and there are no push subscriptions. */ if exists (select * from sysobjects where name = 'MSsubscription_agents') begin set @publisher = NULL -- Not using @publication because share agent case. select top 1 @publisher = publisher from MSsubscription_agents where allow_subscription_copy = 0 IF @publisher is not null BEGIN RAISERROR(21236, 16, -1, @publisher) RETURN (1) END set @publisher = null select top 1 @publisher = publisher from MSreplication_subscriptions where subscription_type = 0 IF @publisher is not null BEGIN RAISERROR(21237, 16, -1, @publisher) RETURN (1) END if exists (select * from MSsubscription_agents) select @tran_found = 1 end /* ** Make sure all merge subscriptions in the current database ** have allow_subscription_copy set to TRUE ** and there are no push subscriptions. */ if exists (select * from sysobjects where name = 'sysmergepublications') begin set @publication = NULL select top 1 @publication = name from sysmergepublications where allow_subscription_copy = 0 IF @publication is not null BEGIN RAISERROR (21204, 16, -1, @publication) RETURN (1) END set @publication = null select top 1 @publication = p.name from sysmergepublications p, sysmergesubscriptions s where p.pubid = s.pubid and s.subid <> s.pubid and db_name = db_name() collate database_default and subscriber_server = convert(nvarchar(4000), SERVERPROPERTY('ServerName')) collate database_default and s.subscription_type = 0 IF @publication is not null BEGIN RAISERROR(21238, 16, -1, @publication) RETURN (1) END -- Does db contains subscriptions? if exists (select * from sysmergesubscriptions where subid <> pubid and db_name = db_name() collate database_default and subscriber_server = convert(nvarchar(4000), SERVERPROPERTY('ServerName')) collate database_default) select @merge_found = 1 /* Retention check : Make sure that the subscription copy is not too old */ declare PC CURSOR LOCAL FAST_FORWARD for select DISTINCT p.name, p.pubid, p.retention from sysmergepublications p, sysmergesubscriptions s where s.subid=p.pubid and s.pubid=p.pubid for read only open PC fetch PC into @publication, @pubid, @retention WHILE (@@fetch_status <> -1) BEGIN /* Compute the retention period cutoff dates per publication */ select @retention_date = dateadd(day, -@retention, getdate()) if @retention is not NULL and @retention > 0 begin if not exists (select coldate from sysmergearticles , MSmerge_genhistory where nickname = art_nick and coldate > @retention_date and sysmergearticles.pubid = @pubid) begin RAISERROR (21306, 16, -1, @publication) return (1) end end fetch PC into @publication, @pubid, @retention END end if @tran_found = 0 and @merge_found = 0 begin raiserror(21239, 16 , -1) return (1) end -- Security check -- Only DBO or sysadmin can do this -- The user also must have create db permissions. exec @retcode = dbo.sp_MSreplcheck_subscribe IF @retcode <> 0 or @@error <> 0 return 1 if @overwrite_existing_file is null set @overwrite_existing_file = 0 -- Check to see if the file already exists declare @exists bit if @overwrite_existing_file = 0 begin exec @retcode = dbo.sp_MSget_file_existence @filename, @exists output if @@error <> 0 or @retcode <> 0 return 1 if @exists <> 0 begin raiserror(21214, 16, -1, @filename) return 1 end end -- Check to see if have write permissions to the file location. -- Try create the file -- Echo text can be anything. select @cmd = 'echo Subscription copy failed. > "' + fn_escapecmdshellsymbolsremovequotes(@filename) collate database_default + '"' exec @retcode = master.dbo.xp_cmdshell @cmd, NO_OUTPUT if @@error <> 0 or @retcode <> 0 begin raiserror(21247, 16, -1, @filename) select @retcode = 1 goto Cleanup end -- File should be created. exec @retcode = dbo.sp_MSget_file_existence @filename, @exists output if @@error <> 0 or @retcode <> 0 begin select @retcode = 1 goto Cleanup end if @exists = 0 begin raiserror(21247,16, -1, @filename) select @retcode = 1 goto Cleanup end /* ** Get the MSSQL DATA path. Note that users can have a SQLDataRoot directory different from SQLPath */ if @temp_dir is null begin exec @retcode = master.dbo.sp_MSget_setup_paths @data_path = @temp_dir output IF @retcode <> 0 or @@error <> 0 return 1 select @temp_dir = @temp_dir + '\DATA\' end else begin -- Check to make sure working dir is valid. exec @retcode = dbo.sp_MSget_file_existence @temp_dir, @exists output if @@error <> 0 or @retcode <> 0 begin select @retcode = 1 goto Cleanup end if @exists = 0 begin raiserror (21037, 16, -1, @temp_dir) select @retcode = 1 goto Cleanup end if substring(@temp_dir, len(@temp_dir), 1) <> '\' select @temp_dir = @temp_dir + '\' end -- Get temp db name -- Use a guid to avoid name colision. declare @dbname sysname select @dbname = db_name() declare @temp_db_name sysname declare @guid_name nvarchar(36) select @guid_name = convert (nvarchar(36), newid()) select @temp_db_name = 'repl_sub_restore_' + @guid_name select @backup_path = @temp_dir + @temp_db_name + '.bak' -- Create table used to signal attach or restored process to do different things if not exists (select * from sysobjects where name = 'MSreplication_restore_stage') begin CREATE TABLE dbo.MSreplication_restore_stage ( stage_id int -- not used for now ) IF @@ERROR <> 0 return 1 end -- First backup the database to the file given -- Overwrite the existing file with INIT option. BACKUP DATABASE @dbname TO DISK = @backup_path WITH INIT if @@error<> 0 begin select @retcode = 1 goto Cleanup end -- Restore it to a temporary working database -- Get phy data and log file name for the temp db select @temp_data_path = @temp_dir + @temp_db_name + '.mdf' select @temp_log_path = @temp_dir + @temp_db_name + '.ldf' -- Get the command select @cmd = 'restore database ' + quotename(@temp_db_name) + ' from disk = ' + quotename(@backup_path,'''') + ' with replace, move ' -- Get the logical file name for data file. select @cmd = @cmd + quotename(rtrim(name),'''') from sysfiles where (status & 0x40) = 0 -- Use passed in filename as phy data file name for the temp db -- Use the passed in file as phy data file for the temp db select @cmd = @cmd + ' to ' + quotename(@temp_data_path,'''') + ', move ' -- Get the logical file name for the log file select @cmd = @cmd + quotename(rtrim(name),'''') from sysfiles where (status & 0x40) <> 0 -- Use the passed in file as phy file for the temp db select @cmd = @cmd + ' to ' + quotename(@temp_log_path,'''') + ' ' exec (@cmd) if @@error<> 0 begin select @retcode = 1 goto Cleanup end -- Once we successfully restored, we delete to back up file to save disk space. if @backup_path is not null begin select @cmd = 'del "' + fn_escapecmdshellsymbolsremovequotes(@backup_path) collate database_default + '"' EXEC master..xp_cmdshell @cmd, NO_OUTPUT set @backup_path = null end -- Prepare the database for detach. 2 things will be done -- 1. Set a flag to indicate that this is a prepare sub db for detach -- 2. For merge, create table to store sysservers info for later fixing up after attach select @cmd = quotename(@temp_db_name) + '.dbo.sp_MSprepare_sub_for_detach' exec @retcode = @cmd @subscriber_srvid = @subscriber_srvid, @subscriber_db = @subscriber_db if @retcode<>0 or @@error<>0 begin select @retcode = 1 goto Cleanup end -- Shink the size of the temp db before detach DBCC SHRINKDATABASE (@temp_db_name, 10) if @@error <> 0 goto Cleanup -- detach the database -- Wait for the db to be closed WAITFOR DELAY '00:00:00.500' exec @retcode = sp_detach_db @temp_db_name if @retcode<>0 or @@error<>0 begin select @retcode = 1 goto Cleanup end -- Delete the log file to save disk space if @temp_log_path is not null begin select @cmd = 'del "' + fn_escapecmdshellsymbolsremovequotes(@temp_log_path) collate database_default + '"' EXEC master..xp_cmdshell @cmd, NO_OUTPUT set @temp_log_path = null end -- Compress the file exec @retcode = master..xp_makecab @cabfilename = @filename, @compression_mode ='mszip', @verbose_level = 0, @filename1 = @temp_data_path if @retcode<>0 or @@error<>0 begin select @retcode = 1 goto Cleanup end Cleanup: if exists (select * from sysobjects where name = 'MSreplication_restore_stage') drop table dbo.MSreplication_restore_stage if exists (select * from master..sysdatabases where name = @temp_db_name collate database_default) begin select @cmd = 'drop database ' + quotename(@temp_db_name) exec (@cmd) end if @backup_path is not null begin select @cmd = 'del "' + fn_escapecmdshellsymbolsremovequotes(@backup_path) collate database_default + '"' EXEC master..xp_cmdshell @cmd, NO_OUTPUT end if @temp_data_path is not null begin select @cmd = 'del "' + fn_escapecmdshellsymbolsremovequotes(@temp_data_path) collate database_default + '"' EXEC master..xp_cmdshell @cmd, NO_OUTPUT end if @temp_log_path is not null begin select @cmd = 'del "' + fn_escapecmdshellsymbolsremovequotes(@temp_log_path) collate database_default + '"' EXEC master..xp_cmdshell @cmd, NO_OUTPUT end if @retcode <> 0 begin select @cmd = 'del "' + fn_escapecmdshellsymbolsremovequotes(@filename) collate database_default + '"' EXEC master..xp_cmdshell @cmd, NO_OUTPUT end return @retcode go EXEC dbo.sp_MS_marksystemobject sp_copysubscription GO print '' print 'Creating procedure sp_attachsubscription' go CREATE PROCEDURE sp_attachsubscription ( @dbname sysname, @filename nvarchar(260), @subscriber_security_mode int = NULL, /* 0 standard; 1 integrated */ @subscriber_login sysname = NULL, @subscriber_password sysname = NULL ) AS SET NOCOUNT ON /* ** Declarations. */ declare @cmd nvarchar(4000) declare @retcode int DECLARE @platform_nt binary declare @copy_created bit declare @exists bit select @platform_nt = 0x1 select @retcode = 0 select @copy_created = 0 select @exists = 0 -- Parameter check: @subscriber_security_mode if @subscriber_security_mode is null begin if ( platform() & @platform_nt ) = @platform_nt select @subscriber_security_mode = 1 else select @subscriber_security_mode = 0 end if ( ( platform() & @platform_nt ) <> @platform_nt and @subscriber_security_mode = 1 ) begin RAISERROR(21038, 16, -1) RETURN (1) end if (@subscriber_security_mode = 0) and (@subscriber_login IS NULL or rtrim(@subscriber_login) = '') set @subscriber_login = 'sa' -- Check to make sure the database does not exists. if exists (select * from master..sysdatabases where name = @dbname collate database_default) begin raiserror(20621, 16, -1, @dbname) return (1) end -- Check to see if users has permissions to create database -- permissions() have to be run in master to return create db permission. declare @pm int exec @retcode = master.dbo.sp_executesql N'select @pm = permissions()', N'@pm int output', @pm output if @@error <> 0 or @retcode <> 0 return 1 if @pm & 1 = 0 begin raiserror(20618, 16, -1) return 1 end -- Decompress the file -- We have to copy the file to another location first. -- (cannot use source as destination') declare @temp_copy nvarchar(260) declare @file_dir nvarchar(260) declare @file_name nvarchar(260) declare @dir_cmd nvarchar(260) -- Set @drive_cmd if needed -- Set temp copy to be the file directory first -- Note @file_dir include '\' if (charindex('\', @filename, 1) = 0) begin select @file_dir = '' select @file_name = @filename end else begin select @file_dir = left(@filename,len(@filename) + 1 - charindex('\', reverse(@filename), 1)) select @file_name = right(@filename, len(@filename) - len(@file_dir)) end -- Get guid name declare @guid_name nvarchar(36) select @guid_name = convert (nvarchar(36), newid()) select @temp_copy = @file_dir + @guid_name + '.tmp' -- copy file select @cmd = 'copy "' + fn_escapecmdshellsymbolsremovequotes(@filename) collate database_default + '" "' + fn_escapecmdshellsymbolsremovequotes(@temp_copy) collate database_default + '"' exec @retcode = master.dbo.xp_cmdshell @cmd, NO_OUTPUT if @@error <> 0 or @retcode <> 0 begin raiserror(21248, 16, -1, @filename) select @retcode = 1 goto Cleanup end exec @retcode = dbo.sp_MSget_file_existence @temp_copy, @exists output if @@error <> 0 or @retcode <> 0 begin select @retcode = 1 goto Cleanup end if @exists = 0 begin raiserror(21247, 16, -1, @temp_copy) select @retcode = 1 goto Cleanup end select @copy_created = 1 -- decompress exec @retcode = master.dbo.xp_unpackcab @cabfilename = @temp_copy, @destination_folder = @file_dir, @verbose_level = 0, @destination_file = @file_name, @suppress_messages = 1 if @@error <> 0 begin select @retcode = 1 goto Cleanup end if @retcode in (1030,1029,2005) begin raiserror(20609, 16, -1, @filename) select @retcode = 1 goto Cleanup end else if @retcode <> 0 -- re-issue the command to get errors begin exec @retcode = master.dbo.xp_unpackcab @cabfilename = @temp_copy, @destination_folder = @file_dir, @verbose_level = 0, @destination_file = @file_name, @suppress_messages = 0 select @retcode = 1 goto Cleanup end -- Attach exec @retcode = dbo.sp_attach_single_file_db @dbname = @dbname, @physname = @filename if @retcode<>0 or @@error<>0 begin raiserror(21248, 16, -1, @filename) select @retcode = 1 goto Cleanup end if isnull(is_srvrolemember('sysadmin'), 0) <> 0 begin select @cmd = quotename(@dbname) + '.dbo.sp_changedbowner' exec @retcode = @cmd N'sa' if @retcode<>0 or @@error<>0 begin select @retcode = 1 goto Cleanup end end -- Prepare the database for detach. 2 things will be done -- 1. Set a flag to indicate that this is a prepare sub db for detach -- 2. For merge, create table to store sysservers info for later fixing up after attach select @cmd = quotename(@dbname) + '.dbo.sp_MSrestore_sub' exec @retcode = @cmd @subscriber_security_mode = @subscriber_security_mode, @subscriber_login = @subscriber_login, @subscriber_password = @subscriber_password if @retcode<>0 or @@error<>0 begin select @retcode = 1 goto Cleanup end Cleanup: if @retcode <> 0 begin -- The files will be deleted if some thing failed. if exists (select * from master..sysdatabases where name = @dbname collate database_default) begin select @cmd = 'drop database ' + quotename(@dbname) exec (@cmd) end end if @temp_copy is not null begin -- Restore the original file, ignore errors if @retcode <> 0 and @copy_created = 1 begin select @cmd = 'copy "' + fn_escapecmdshellsymbolsremovequotes(@temp_copy) collate database_default + '" "' + fn_escapecmdshellsymbolsremovequotes(@filename) collate database_default + '"' exec master.dbo.xp_cmdshell @cmd, NO_OUTPUT end -- Delete the temp file. select @cmd = 'del "' + fn_escapecmdshellsymbolsremovequotes(@temp_copy) collate database_default+ '"' EXEC master..xp_cmdshell @cmd, NO_OUTPUT end return @retcode go EXEC dbo.sp_MS_marksystemobject sp_attachsubscription GO print '' print 'Creating procedure sp_MSrestore_sub_merge' go CREATE PROCEDURE sp_MSrestore_sub_merge ( @subscriber_security_mode int, @subscriber_login sysname, @subscriber_password nvarchar(524) ) AS SET NOCOUNT ON declare @retcode int declare @detached int declare @attached int DECLARE @publisher sysname /* Expression used in the cursor */ DECLARE @publisher_db sysname /* Expression used in the cursor */ DECLARE @publication sysname /* Expression used in the cursor */ DECLARE @distributor sysname /* Expression used in the cursor */ declare @subnickname int declare @subid uniqueidentifier declare @detached_subid uniqueidentifier declare @subscriber_srvid int declare @subscriber_server sysname declare @subscriber_db sysname declare @enabled_for_syncmgr_int int declare @enabled_for_syncmgr nvarchar(5) declare @retention int declare @retention_date datetime declare @pubid uniqueidentifier declare @distributor_security_mode int declare @distributor_login sysname declare @distributor_password nvarchar(524) declare @publisher_security_mode int declare @publisher_login sysname declare @publisher_password nvarchar(524) -- Initialization select @retcode = 0 select @detached = 3 select @attached = 4 select @subscriber_srvid = 0 select @subscriber_db = db_name() IF EXISTS (SELECT * from sysmergepublications where allow_subscription_copy = 0) BEGIN RAISERROR (21205, 16, -1, @publication) RETURN (1) END /* Retention check : Make sure that the subscription copy is not too old */ declare PC CURSOR LOCAL FAST_FORWARD for select DISTINCT p.name, p.pubid, p.retention from sysmergepublications p, sysmergesubscriptions s where s.subid=p.pubid and s.pubid=p.pubid for read only open PC fetch PC into @publication, @pubid, @retention WHILE (@@fetch_status <> -1) BEGIN /* Compute the retention period cutoff dates per publication */ select @retention_date = dateadd(day, -@retention, getdate()) if @retention is not NULL and @retention > 0 begin if not exists (select coldate from sysmergearticles , MSmerge_genhistory where nickname = art_nick and coldate > @retention_date and sysmergearticles.pubid = @pubid) begin RAISERROR (21307, 16, -1, @publication) return (1) end end fetch PC into @publication, @pubid, @retention END -- Touch up system tables for merge subscriptions -- Open a cursor for all subscriptions DECLARE hCallsubscriptions CURSOR LOCAL FAST_FORWARD FOR SELECT subid, subscriber_server from sysmergesubscriptions FOR READ ONLY OPEN hCallsubscriptions FETCH hCallsubscriptions INTO @subid, @subscriber_server WHILE (@@fetch_status <> -1) BEGIN /* ** Validate that the subscriber is a valid server and has an entry in sysservers, else add it */ select @subscriber_srvid = NULL select @subscriber_srvid = srvid from master..sysservers where UPPER(srvname) = UPPER(@subscriber_server) collate database_default IF @subscriber_srvid IS NULL BEGIN EXECUTE @retcode = dbo.sp_addserver @subscriber_server IF @@error <> 0 OR @retcode <> 0 BEGIN RAISERROR (14010, 16, -1) RETURN (1) END select @subscriber_srvid = srvid from master..sysservers where UPPER(srvname) = UPPER(@subscriber_server) collate database_default IF @subscriber_srvid IS NULL BEGIN RAISERROR (14010, 16, -1) RETURN (1) END END FETCH hCallsubscriptions INTO @subid, @subscriber_server END /* ** Touch up srvid of existing rows in sysmergesubscriptions that correspond ** to the subscription that is not attached. Note that this has to be a bulk ** update since doing it a row at a time will cause the unique_pubsrvdb constaint ** in sysmergesubscriptions to be violated. */ update sysmergesubscriptions set srvid = fn_serverid(subscriber_server) where status <> @detached if @@ERROR <> 0 goto Cleanup -- Open a cursor for all subscriptions that have a status of 'detached' DECLARE hCdetachedsubscriptions CURSOR LOCAL FAST_FORWARD FOR SELECT subid from sysmergesubscriptions where status = @detached FOR READ ONLY OPEN hCdetachedsubscriptions FETCH hCdetachedsubscriptions INTO @detached_subid WHILE (@@fetch_status <> -1) BEGIN /* ** Select the srvid of the local server */ select @subscriber_srvid = 0 /* Generate a guid for the Subscriber ID */ set @subid = newid() /* Look for existing nickname from any other subscription */ exec dbo.sp_MSgetreplnick NULL, NULL , NULL, @subnickname out if @@ERROR <> 0 goto Cleanup /* Generate a new replica nickname from the @subid */ if (@subnickname is null) begin EXECUTE dbo.sp_MSgenreplnickname @subid, @subnickname output if @@ERROR <> 0 goto Cleanup end /* ** Touch up existing rows in sysmergesubscriptions & MSmerge_replinfo. ** Set status of attached subsription as "attached" */ update sysmergesubscriptions set subid = @subid, srvid = @subscriber_srvid, subscriber_server = @@servername, db_name = @subscriber_db, status = @attached, login_name = suser_sname(suser_sid()) where subid = @detached_subid if @@ERROR <> 0 goto Cleanup update MSmerge_replinfo set repid = @subid, replnickname = @subnickname where repid = @detached_subid if @@ERROR <> 0 goto Cleanup FETCH hCdetachedsubscriptions INTO @detached_subid END /* Add pull subscription agents only if MSsubscription_properties exists */ if exists (select * from sysobjects where name = 'MSsubscription_properties') begin -- Add the agents for pull or anonymous subscriptions. DECLARE hCmergesubscription CURSOR LOCAL FAST_FORWARD FOR SELECT publisher, publisher_db, publication, distributor, enabled_for_syncmgr, distributor_security_mode, distributor_login, distributor_password, publisher_security_mode, publisher_login, publisher_password FROM MSsubscription_properties -- only do this for merge subscriptions where publication_type = 2 --where publication is not NULL and -- publication <> N'' and -- subscription_type <> @push FOR READ ONLY OPEN hCmergesubscription FETCH hCmergesubscription INTO @publisher, @publisher_db, @publication, @distributor, @enabled_for_syncmgr_int, @distributor_security_mode, @distributor_login, @distributor_password, @publisher_security_mode, @publisher_login, @publisher_password WHILE (@@fetch_status <> -1) BEGIN /* Enable the subscription to be synchronized via SyncMgr if the original one was */ if @enabled_for_syncmgr_int = 0 set @enabled_for_syncmgr = 'false' else set @enabled_for_syncmgr = 'true' if @distributor_security_mode = 0 and @distributor_login is NULL select @distributor_login = 'sa' if @publisher_security_mode = 0 and @publisher_login is NULL select @publisher_login = 'sa' EXEC @retcode = master.dbo.xp_repl_help_connect @distributor_password OUTPUT IF @@error <> 0 OR @retcode <> 0 begin select @retcode = 1 goto Cleanup end EXEC @retcode = master.dbo.xp_repl_help_connect @publisher_password OUTPUT IF @@error <> 0 OR @retcode <> 0 begin select @retcode = 1 goto Cleanup end EXECUTE @retcode = dbo.sp_addmergepullsubscription_agent @publisher = @publisher, @publisher_db = @publisher_db, @publication = @publication, @distributor = @distributor, @subscriber_security_mode = @subscriber_security_mode, @subscriber_login = @subscriber_login, @subscriber_password = @subscriber_password, @publisher_security_mode = @publisher_security_mode, @publisher_login = @publisher_login, @publisher_password = @publisher_password, @publisher_encrypted_password = 0, @distributor_security_mode = @distributor_security_mode, @distributor_login = @distributor_login, @distributor_password = @distributor_password, @encrypted_password = 0, @frequency_type = 2 , /* 2== OnDemand */ @enabled_for_syncmgr = @enabled_for_syncmgr, @reserved = 'attach_subscription' if @@error <> 0 or @retcode <> 0 begin select @retcode = 1 goto Cleanup end FETCH hCmergesubscription INTO @publisher, @publisher_db, @publication, @distributor, @enabled_for_syncmgr_int, @distributor_security_mode, @distributor_login, @distributor_password, @publisher_security_mode, @publisher_login, @publisher_password END end else begin /* ** Check to see if MSsubscription_properties table exists. ** If not, create it. */ exec @retcode = dbo.sp_MScreate_sub_tables @tran_sub_table = 0, @property_table = 1, @sqlqueue_table = 0 if @@error <> 0 or @retcode <> 0 begin select @retcode = 1 goto Cleanup end end return 0 Cleanup: return 1 go EXEC dbo.sp_MS_marksystemobject sp_MSrestore_sub_merge GO print '' print 'Creating procedure sp_MSrestore_sub_tran' go CREATE PROCEDURE sp_MSrestore_sub_tran ( @subscriber_security_mode int, @subscriber_login sysname, @subscriber_password nvarchar(524) ) AS SET NOCOUNT ON /* ** Declarations. */ declare @push int declare @retcode int DECLARE @publisher sysname /* Expression used in the cursor */ DECLARE @publisher_db sysname /* Expression used in the cursor */ DECLARE @publication sysname /* Expression used in the cursor */ -- Initialization select @push = 0 select @retcode = 0 -- Reset agent_id and anonymous agent id and time update MSreplication_subscriptions set agent_id = NULL, subid = NULL, distribution_agent = NULL, time = getdate() if @@error <> 0 begin select @retcode = 1 goto Cleanup end -- Set attach_state value -- It is only used by pull subscription. -- The attach state is "attached but not processed". update MSsubscription_agents set attach_state = 1 -- Add the agents for pull or anonymous subscriptions. DECLARE hCsubscription CURSOR LOCAL FAST_FORWARD FOR SELECT publisher, publisher_db, publication FROM MSreplication_subscriptions where publication is not NULL and publication <> N'' and subscription_type <> @push FOR READ ONLY OPEN hCsubscription FETCH hCsubscription INTO @publisher, @publisher_db, @publication WHILE (@@fetch_status <> -1) BEGIN EXECUTE @retcode = dbo.sp_addpullsubscription_agent @publisher = @publisher, @publisher_db = @publisher_db, @publication = @publication, @subscriber_security_mode = @subscriber_security_mode, @subscriber_login = @subscriber_login, @subscriber_password = @subscriber_password, @frequency_type = 2 , /* 2== OnDemand */ @reserved = 'no_change_to_properties' if @@error <> 0 or @retcode <> 0 begin select @retcode = 1 goto Cleanup end FETCH hCsubscription INTO @publisher, @publisher_db, @publication END Cleanup: -- Nothing to cleanup return @retcode go EXEC dbo.sp_MS_marksystemobject sp_MSrestore_sub_tran GO print '' print 'Creating procedure sp_MSrestore_sub' go CREATE PROCEDURE sp_MSrestore_sub ( @subscriber_security_mode int, @subscriber_login sysname, @subscriber_password nvarchar(524) ) AS SET NOCOUNT ON /* ** Declarations. */ declare @retcode int -- Initialization select @retcode = 0 if exists (select * from sysobjects where name = 'MSreplication_subscriptions') begin exec @retcode = dbo.sp_MSrestore_sub_tran @subscriber_security_mode = @subscriber_security_mode, @subscriber_login = @subscriber_login, @subscriber_password = @subscriber_password if @@error <> 0 or @retcode <> 0 begin select @retcode = 1 goto Cleanup end end if exists (select * from sysobjects where name = 'sysmergesubscriptions') begin exec @retcode = dbo.sp_MSrestore_sub_merge @subscriber_security_mode = @subscriber_security_mode, @subscriber_login = @subscriber_login, @subscriber_password = @subscriber_password if @@error <> 0 or @retcode <> 0 begin select @retcode = 1 goto Cleanup end end Cleanup: if exists (select * from sysobjects where name = 'MSreplication_restore_stage') drop table MSreplication_restore_stage return @retcode go EXEC dbo.sp_MS_marksystemobject sp_MSrestore_sub GO raiserror('Creating procedure sp_validatemergepullsubscription', 0,1) GO CREATE PROCEDURE sp_validatemergepullsubscription (@publication sysname, @publisher sysname, @publisher_db sysname, @level tinyint ) AS declare @subscriber_srvid int declare @retcode int declare @pubid uniqueidentifier declare @subscriber sysname declare @subscriber_db sysname /* ** Security Check */ EXEC @retcode = dbo.sp_MSreplcheck_publish IF @@ERROR <> 0 or @retcode <> 0 return (1) select @subscriber = @@SERVERNAME, @subscriber_db=db_name() select @subscriber_srvid = srvid from master..sysservers where LOWER(srvname)=LOWER(@subscriber) collate database_default select @pubid=pubid from sysmergepublications where LOWER(publisher)=LOWER(@publisher) and publisher_db=@publisher_db and name=@publication if @pubid is NULL begin raiserror (20026, 16, -1, @publication) return (1) end if @level <0 or @level > 3 begin raiserror(21184, 16, -1, '@level', '1', '2','3') return (1) end if not exists (select * from sysmergesubscriptions where pubid=@pubid and db_name=@subscriber_db and srvid=@subscriber_srvid) begin raiserror(14055, 16, -1) return (1) end update sysmergesubscriptions set validation_level=@level where pubid=@pubid and db_name=@subscriber_db and srvid=@subscriber_srvid if @@ERROR<>0 return (1) return (0) go exec dbo.sp_MS_marksystemobject sp_validatemergepullsubscription go grant exec on dbo.sp_validatemergepullsubscription to public go print '' print 'Creating procedure sp_MSprepare_sub_for_detach' go CREATE PROCEDURE sp_MSprepare_sub_for_detach @subscriber_srvid int, @subscriber_db sysname as set nocount on declare @detached int select @detached = 3 -- Stage: attach and restore subscription. update dbo.MSreplication_restore_stage set stage_id = 2 if @@error <> 0 return 1 /* Touch up the merge subscriptions for detach */ if exists (select * from sysobjects where name = 'sysmergesubscriptions') begin /* Mark all subscriptions to have a status of detached */ update sysmergesubscriptions set status = @detached where srvid = @subscriber_srvid and db_name = @subscriber_db if @@error <> 0 return 1 end if exists (select * from sysobjects where name = 'MSsub_identity_range') begin -- Set range to 0 so that the attached db will get new ranges -- Refer to sp_MSsub_check_identity update MSsub_identity_range set range = 0 if @@error <> 0 return 1 end go EXEC dbo.sp_MS_marksystemobject sp_MSprepare_sub_for_detach GO print '' print 'Creating procedure sp_MSsub_check_identity' go CREATE PROCEDURE sp_MSsub_check_identity @lower_bound_id int as declare @retcode int declare @cmd nvarchar(1000) declare @objid int, @threshhold bigint, @range bigint, @next_seed bigint declare @last_seed bigint, @identity_so_far bigint, @threshold int declare @table_name sysname declare @qualname nvarchar(512) -- Security Check EXEC @retcode = dbo.sp_MSreplcheck_subscribe IF @@ERROR <> 0 or @retcode <> 0 RETURN(1) -- This proc will be called by distribution agent called repeatedly until -- one result returned if exists (select * from sysobjects where name = 'MSsub_identity_range') begin while 1 = 1 begin select @objid = null select top 1 @objid = objid from MSsub_identity_range where objid > @lower_bound_id order by objid ASC if @objid is null break select @lower_bound_id = @objid -- Since we don't always clean up the subscriber, Skipping invalid entry. if object_name(@objid) is null continue if objectproperty(@objid, 'TableHasIdentity') <> 1 continue exec sp_MSget_qualified_name @objid, @qualname OUTPUT select @range = range, @last_seed = last_seed, @threshold = threshold from MSsub_identity_range where objid=@objid if @range = 0 -- First time after initial bcp, always request a new range -- return this object break else begin -- Leave one slot unused. This is to prevent violation of primary key constraint -- if the next value is used by a subscriber and the publisher has received it. -- It seems the pk constraint will be validated before this check. declare @actual_range int if @range > 0 select @actual_range = @range - 1 else select @actual_range = @range + 1 select @identity_so_far = ident_current(@qualname) if 100*(@identity_so_far - @last_seed)/@actual_range >= @threshold -- Need new range break end select @lower_bound_id = @objid end end select @table_name = object_name(@objid) -- Return nothing if @table_name is null, which means no more table needs to be adjust select 'objid' = @objid, 'table_name' = @table_name where @objid is not null go EXEC dbo.sp_MS_marksystemobject sp_MSsub_check_identity GO print '' print 'Creating procedure sp_MSsub_cleanup_orphans' go CREATE PROCEDURE sp_MSsub_cleanup_orphans AS /* ** Security Check */ -- Internal sp, not granted to public. -- Ignore all errrors if exists (select * from sysobjects where name = 'MSreplication_objects') begin delete MSreplication_objects where not exists (select * from sysobjects where name = object_name) if not exists (select * from MSreplication_objects) drop table MSreplication_objects end if exists (select * from sysobjects where name = 'MSsub_identity_range') begin delete MSsub_identity_range where not exists (select * from sysobjects where id = objid) if not exists (select * from MSsub_identity_range) drop table MSsub_identity_range end GO EXEC dbo.sp_MS_marksystemobject sp_MSsub_cleanup_orphans GO print '' print 'Creating procedure sp_MSsub_cleanup_prop_table' go CREATE PROCEDURE sp_MSsub_cleanup_prop_table AS /* ** Security Check */ -- Internal sp, not granted to public. -- Ignore all errrors declare @drop_table bit -- Init to drop table select @drop_table = 1 if exists (select * from sysobjects where name = 'MSreplication_subscriptions') begin if exists (select * from MSreplication_subscriptions where subscription_type <> 0) select @drop_table = 0 end if exists (select * from sysobjects where name = 'sysmergesubscriptions') begin if exists (select * from sysmergesubscriptions where subid <> pubid and db_name = db_name() and subscriber_server = convert(sysname, SERVERPROPERTY('ServerName')) collate database_default and subscription_type <> 0) select @drop_table = 0 end if @drop_table = 1 drop table dbo.MSsubscription_properties GO EXEC dbo.sp_MS_marksystemobject sp_MSsub_cleanup_prop_table GO print '' print 'Creating procedure sp_MSreseed' go CREATE PROCEDURE sp_MSreseed( @objid int, @next_seed bigint, @range bigint, @is_publisher int = 0, @check_only bit = 0, @drop_only bit = 0, @initial_setting bit = 0, @bound_value bigint = 0 ) AS declare @min_value bigint declare @max_value bigint declare @constraintname sysname declare @artid uniqueidentifier declare @min_str nvarchar(20) declare @identity_column sysname declare @colid int declare @colname sysname declare @max_str nvarchar(20) declare @owner sysname declare @tablename sysname declare @qualname nvarchar(270) declare @dbname sysname declare @prefix sysname SET NOCOUNT ON select @prefix = 'repl_identity_range_' select @colid=1 select @dbname=db_name() select @colname=name from syscolumns where colid=@colid and id = @objid while COLUMNPROPERTY(@objid, @colname, 'IsIdentity')=0 and @colname is not NULL begin select @colid = @colid + 1 select @colname=name from syscolumns where colid=@colid and id = @objid end if @colname is NULL begin raiserror('there is no identity column in this table', 16, -1) return (1) end if @range > 0 begin select @min_value = @next_seed if @initial_setting = 1 select @min_value = @bound_value - 1 -- allow for race condition with ident_current. -- @next_seed + @range can be used by this db, but not other db. -- Leave one slot unused. This is to prevent violation of primary key constraint -- if the next value is used by a subscriber and the publisher has received it. -- It seems the pk constraint will be validated before this check. -- select @max_value = @next_seed + @range + 1 select @max_value = @next_seed + @range select @next_seed=@next_seed + 1 end else begin select @max_value = @next_seed if @initial_setting = 1 select @max_value = @bound_value + 1 -- allow for race condition with ident_current. -- @next_seed + @range can be used by this db, but not other db. -- Leave one slot unused. This is to prevent violation of primary key constraint -- if the next value is used by a subscriber and the publisher has received it. -- It seems the pk constraint will be validated before this check. -- select @min_value = @next_seed + @range - 1 select @min_value = @next_seed + @range select @next_seed=@next_seed - 1 end select @min_str = convert(nvarchar, @min_value) select @max_str = convert(nvarchar, @max_value) select @owner = user_name(uid) from sysobjects where id = @objid select @tablename = object_name(@objid) select @qualname = QUOTENAME(@owner) + '.' + QUOTENAME(@tablename) if @check_only = 0 begin DBCC CHECKIDENT(@qualname, RESEED, @next_seed) with no_infomsgs if @@ERROR<>0 return (1) end if @is_publisher < 0 begin -- Used by tran -- Publisher side constraint maybe transfered to subscriber. -- If so, it will be dropped with code below. select @constraintname = NULL select @constraintname = name from sysobjects where name like @prefix + 'tran_[0-9]%' and xtype='C' and parent_obj = @objid if @constraintname is not null begin exec ('alter table '+ @qualname + ' drop constraint ' + @constraintname) if @@ERROR<>0 return (1) end select @constraintname = @prefix + 'tran_' + convert(nvarchar(10), @objid) end else begin -- Used by merge select @artid=artid from dbo.sysmergearticles where objid=@objid select @constraintname = @prefix + 'pub_' + convert(nvarchar(36), @artid) select @constraintname = REPLACE(@constraintname, '-', '_') if exists (select * from sysobjects where name = @constraintname and xtype='C') begin exec ('alter table '+ @qualname + ' drop constraint ' + @constraintname) if @@ERROR<>0 return (1) end select @constraintname = @prefix + 'repub_' + convert(nvarchar(36), @artid) select @constraintname = REPLACE(@constraintname, '-', '_') if exists (select * from sysobjects where name = @constraintname and xtype='C') begin exec ('alter table '+ @qualname + ' drop constraint ' + @constraintname) if @@ERROR<>0 return (1) end select @constraintname = @prefix + 'sub_' + convert(nvarchar(36), @artid) select @constraintname = REPLACE(@constraintname, '-', '_') if exists (select * from sysobjects where name = @constraintname and xtype='C') begin exec ('alter table '+ @qualname + ' drop constraint ' + @constraintname) if @@ERROR<>0 return (1) end if @is_publisher=1 select @constraintname = @prefix + 'pub_' + convert(nvarchar(36), @artid) else if @is_publisher = 2 select @constraintname = @prefix + 'repub_' + convert(nvarchar(36), @artid) else select @constraintname = @prefix + 'sub_' + convert(nvarchar(36), @artid) select @constraintname = REPLACE(@constraintname, '-', '_') end -- Don't add new constraint if only drop is needed. if @drop_only = 1 return (0) declare @qualcolname sysname select @qualcolname = quotename(@colname) exec ('alter table '+ @qualname + ' with NOCHECK add CONSTRAINT ' + @constraintname + ' check NOT FOR REPLICATION ( ' + @qualcolname + ' > ' + @min_str + ' and ' + @qualcolname + ' < ' + @max_str + ')') if @@ERROR<>0 return (1) return (0) GO EXEC dbo.sp_MS_marksystemobject sp_MSreseed GO print '' print 'Creating procedure sp_MSsub_set_identity' go CREATE PROCEDURE sp_MSsub_set_identity @objid int, @threshold int, @range bigint, @next_seed bigint as declare @retcode int -- Security Check EXEC @retcode = dbo.sp_MSreplcheck_subscribe IF @@ERROR <> 0 or @retcode <> 0 RETURN(1) -- Stored last_seed in @next_seed select @next_seed = @next_seed - @range update MSsub_identity_range set last_seed = @next_seed, threshold = @threshold, range = @range where objid = @objid IF @@ERROR <> 0 return 1 -- RESEED and change constraint exec @retcode = dbo.sp_MSreseed @objid = @objid, @next_seed = @next_seed, @range = @range, @is_publisher = -1 IF @@ERROR <> 0 OR @retcode <> 0 return 1 go EXEC dbo.sp_MS_marksystemobject sp_MSsub_set_identity GO print '' print 'Creating procedure sp_MSinstance_qv' go create procedure sp_MSinstance_qv @qv varchar(10) as begin declare @qv_value varchar(10) set nocount on -- ------------------------------------------------------------- -- -- BUGBUG 236535 : IA64 workaround -- -- since xp_qv has not been ported yet - detect the -- the platform and preset the config for IA64 servers -- -- NOTE : this code should be later cleaned up -- once SETUP is completely functional on IA64 -- -- ------------------------------------------------------------- declare @fia64 bit create table #tosversion ( propid int, propname sysname collate database_default, value int null, charvalue nvarchar(255) collate database_default) insert into #tosversion (propid, propname, value, charvalue) exec master.dbo.xp_msver N'Platform' select @fia64 = case when patindex(N'%IA64%', charvalue) != 0 then 1 else 0 end from #tosversion if (@fia64 = 1) begin select @qv_value = 0 end else begin if serverproperty('instancename') is null exec @qv_value = master.dbo.xp_qv @qv else begin declare @instance_name varchar(257) select @instance_name = cast(serverproperty('instancename') as varchar(257)) exec @qv_value = master.dbo.xp_qv @qv, @instance_name end end -- ------------------------------------------------------------- return @qv_value end go EXEC dbo.sp_MS_marksystemobject sp_MSinstance_qv GO print '' print 'Creating procedure sp_MSget_shared_agent' go CREATE PROCEDURE sp_MSget_shared_agent ( @server_name sysname, @database_name sysname, @agent_type int, @publisher sysname = NULL -- Only usec by third party. ,@publisher_db sysname = NULL -- Only usec by third party. ) AS declare @server_id smallint select @server_id = srvid from master..sysservers where UPPER(srvname) = UPPER(@server_name) collate database_default -- push agents to SQL publications if @agent_type = 0 begin if object_id('syssubscriptions') is not null begin select top 1 N'job_id' = distribution_jobid from syssubscriptions s, sysarticles a, syspublications p where srvid = @server_id and dest_db = @database_name and subscription_type = 0 and independent_agent = 0 and s.artid = a.artid and p.pubid = a.pubid end end -- push agents to third party else if @agent_type = 1 begin if object_id('MSsubscriptions') is not null begin declare @publisher_id smallint select top 1 @publisher_id from master..sysservers where UPPER(srvname) = UPPER(@publisher) collate database_default select top 1 N'job_id' = job_id from MSdistribution_agents where subscriber_id = @server_id and subscriber_db = @database_name and publication = N'ALL' and publisher_id = @publisher_id and publisher_db = @publisher_db and subscription_type = 0 end end else if @agent_type = 2 begin if object_id('MSreplication_subscriptions') is not null begin -- For subscriptions added through Active X control -- where there's no local agent created, we still don't -- want to create new agent. select top 1 N'job_id' = agent_id from MSreplication_subscriptions where UPPER(publisher) = UPPER(@server_name) and publisher_db = @database_name and independent_agent = 0 and subscription_type in (1,2) end end GO EXEC dbo.sp_MS_marksystemobject sp_MSget_shared_agent GO print '' print 'Creating procedure sp_MSrepl_backup_start' go create procedure sp_MSrepl_backup_start as declare @sync_bit int declare @dist_bit int set nocount on set @sync_bit = 32 set @dist_bit = 16 -- If this is a distribution database and it is marked by 'sync with backup' if exists (select * from master.dbo.sysdatabases where name = db_name() collate database_default and category & (@sync_bit | @dist_bit) = @sync_bit | @dist_bit) begin update MSrepl_backup_lsns set next_xact_id = t2.xact_id, next_xact_seqno = m.xact_seqno from (select tm.publisher_database_id, max(tm.xact_seqno) from -- max seqno of xacts not involved in partial tran processing (select t.publisher_database_id, max(substring(t.xact_seqno, 1, 10)) from MSrepl_transactions t where not t.xact_id = 0x0 group by t.publisher_database_id, substring(t.xact_seqno, 1, 10) having count(t.xact_seqno) < 2 union -- max seqno of xacts involved in and completed partial tran processing select t.publisher_database_id, max(substring(xact_seqno, 1, 10)) from MSrepl_transactions t where not t.xact_id = 0x0 and t.xact_id = substring(t.xact_seqno, 1, 10) group by t.publisher_database_id )as tm(publisher_database_id, xact_seqno) -- derived table containing up to 2 rows per publication_database_id group by tm.publisher_database_id -- derived table containing up to 1 row per publication_database_id )as m(publisher_database_id, xact_seqno), MSrepl_transactions t2 where m.publisher_database_id = MSrepl_backup_lsns.publisher_database_id and t2.publisher_database_id = MSrepl_backup_lsns.publisher_database_id and t2.xact_seqno = m.xact_seqno if @@error <> 0 return 1 end return 0 go EXEC dbo.sp_MS_marksystemobject sp_MSrepl_backup_start GO print '' print 'Creating procedure sp_MSrepl_backup_complete' go create procedure sp_MSrepl_backup_complete as declare @sync_bit int declare @dist_bit int set nocount on set @sync_bit = 32 set @dist_bit = 16 -- If this is a distribution database and it is marked by 'sync with backup' if exists (select * from master.dbo.sysdatabases where name = db_name() collate database_default and category & (@sync_bit | @dist_bit) = @sync_bit | @dist_bit) begin update MSrepl_backup_lsns set valid_xact_id = next_xact_id, valid_xact_seqno = next_xact_seqno if @@error <> 0 return 1 end return 0 go EXEC dbo.sp_MS_marksystemobject sp_MSrepl_backup_complete GO -- -- sp_MSadd_compensating_cmd -- -- Owner: KaushikC -- -- Proc executed from publisher that POSTS COMPENSATING command into -- Publisher Log OR Inserts COMPENSATING command into Distributor -- command table for a given subscriber/subscriberdb based on the mode -- -- Parameters: -- @orig_srv originating subscriber -- @orig_db subscriber db -- @command command or command fragment (max 4000 chars) -- @article_id article id -- @publication_id publication id -- @cmdstate flag to indicate command fragment - to handle case -- where actual commands len exceeds 4000 chars -- @mode mode of operation, 0 = POST IN PUBLISHER LOG -- 1 = INSERT IN DISTRIBUTOR COMMAND TABLE -- @setprefix flag to indicate if we should prefix command with originator info -- -- Security: Public access. Internal security check for publish -- raiserror('Creating procedure sp_MSadd_compensating_cmd', 0,1) go CREATE PROCEDURE sp_MSadd_compensating_cmd( @orig_srv sysname, @orig_db sysname, @command nvarchar(4000), @article_id int, @publication_id int, @cmdstate bit=0, @mode int=0, @setprefix bit=1 ) AS BEGIN set nocount on declare -- -- variable declarations for all modes -- @retcode int, @command_id int, -- command sequence @partial_cmd int, -- partial command flag @curlen int, -- current length to read @start_index int, -- index to start reading @max_fragment int, -- max binary fragment @full_command nvarchar(4000), -- qualified command @readsize int, -- read length chars or bytes based on mode @mode_postpublog int, @mode_insdistcmd int, -- -- variable declarations specific to mode = 1 -- @partial_cmdbit bit, -- partial command flag @xact_seqno varbinary(16), @publisher_id int, -- publisher ID @publisher_db sysname, -- publisher Db @distributor sysname, -- distribution server @distribdb sysname, -- distribution db @charsize int, -- char size @binary_cmd varbinary(1024), -- Binary converted command @distproc nvarchar(300) -- RPC string -- -- Security Check -- exec @retcode = dbo.sp_MSreplcheck_publish if ((@@ERROR != 0) or (@retcode != 0)) return(1) -- -- Initialize -- select @mode_postpublog = 0, @mode_insdistcmd = 1 if (@mode NOT in (@mode_postpublog,@mode_insdistcmd)) return(1) -- -- We will not post final partial empty(may contain space) command -- since logreader skips empty commands and this causes distribution -- agent to get confused when it selects the commands to read. -- If this partial command happens to be the final partial command which -- has a single space - then add a comment -- if ((len(@command) = 0) and (@cmdstate = 0)) select @command = N'/*c*/' -- -- process based on @mode -- if (@mode = @mode_insdistcmd) begin select @publisher_db = db_name(), @publisher_id = srvid from master.dbo.sysservers where UPPER(srvname) = UPPER(@@servername) collate database_default -- -- Get distribution server information for remote RPC calls -- EXECUTE @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT, @distribdb = @distribdb OUTPUT if ((@@ERROR != 0) or (@retcode != 0)) return(1) -- -- Get the new xact_seqno -- create table #new_xact_seqno ( seqno varbinary(16) NOT NULL ) select @distproc = RTRIM(@distributor) + '.' + @distribdb +'.dbo.sp_MSget_new_xact_seqno' insert into #new_xact_seqno EXECUTE @retcode = @distproc @publisher_id = @publisher_id, @publisher_db = @publisher_db, @len = 14 if ((@@ERROR != 0) or (@retcode != 0)) return(1) select @xact_seqno = seqno from #new_xact_seqno select @distproc = RTRIM(@distributor) + '.' + @distribdb +'.dbo.sp_MSadd_repl_command' end -- -- Do the command insertion in a tran -- select @full_command = case when (@setprefix = 1) then QUOTENAME(@orig_srv) + QUOTENAME(@orig_db) + @command else @command end begin tran sp_MSadd_compensating_cmd -- -- process the command -- for @mode_postpublog : just call sp_replpostcmd and that will do the job -- for @mode_insdistcmd : break the command into 1024 sized commands and add -- if (@mode = @mode_postpublog) begin select @partial_cmd = CASE when (@cmdstate = 1) then 1 else 0 END exec @retcode = dbo.sp_replpostcmd @partial_cmd, @publication_id, @article_id, 12, @full_command if (@@ERROR != 0 or @retcode != 0) GOTO UNDO end else if (@mode = @mode_insdistcmd) begin select @command_id = 0, @start_index = 1, @max_fragment = 1024, @charsize = 2, @curlen = LEN(@full_command), @readsize = DATALENGTH(@full_command) while (@readsize > 0) begin -- set command id select @command_id = @command_id + 1 -- Check if we have to process partial command if (@readsize > @max_fragment) begin -- -- we have partial command to send -- select @curlen = @max_fragment / @charsize select @partial_cmdbit = 1, @binary_cmd = CAST( SUBSTRING(@full_command, @start_index, @curlen) AS varbinary(1024)), @readsize = @readsize - @max_fragment select @start_index = @start_index + @curlen select @curlen = @readsize / @charsize end else begin -- -- last fragment to send - end of command -- check for command state - if state is PARTIAL_CMD (1) -- then set the partial bit even though this is the last fragment -- select @partial_cmdbit = CASE when (@cmdstate = 1) then 1 else 0 END, @binary_cmd = CAST( SUBSTRING(@full_command, @start_index, @curlen) AS varbinary(1024)), @readsize = 0 end -- -- Add the command to the distributor -- EXECUTE @retcode = @distproc @publisher_id = @publisher_id, @publisher_db = @publisher_db, @xact_seqno = @xact_seqno, @type = 12, @article_id = @article_id, @command_id = @command_id, @partial_command = @partial_cmdbit, @command = @binary_cmd if (@@ERROR != 0 or @retcode != 0) GOTO UNDO end -- end of while loop end -- end of if (@mode = @mode_insdistcmd) -- -- Command(s) added successfully - End Tran -- commit tran sp_MSadd_compensating_cmd return (0) UNDO: -- -- Error - Rollback -- IF (@@TRANCOUNT > 0) begin ROLLBACK TRAN sp_MSadd_compensating_cmd if (@@TRANCOUNT > 0) COMMIT TRAN end return (1) END go EXEC dbo.sp_MS_marksystemobject sp_MSadd_compensating_cmd GO -- -- System UDF fn_varbintohexstr -- This function takes as input a varbinary -- and returns the Hexadecimal representation string -- create function dbo.fn_varbintohexstr ( @pbinin varbinary(8000) ) returns nvarchar(4000) as begin declare @pstrout nvarchar(4000) select @pstrout = master.dbo.fn_varbintohexsubstring(1,@pbinin,1,0) return @pstrout end go -- -- System UDF fn_varbintohexsubstring -- This function takes as input a varbinary, and start offset and length -- and returns the Hexadecimal representation string for the given substring -- create function dbo.fn_varbintohexsubstring ( @fsetprefix bit = 1 -- append '0x' to the output ,@pbinin varbinary(8000) -- input binary stream ,@startoffset int = 1 -- starting offset ,@cbytesin int = 0 -- length of input to consider, 0 means total length ) returns nvarchar(4000) as begin declare @pstrout nvarchar(4000) ,@i int ,@firstnibble int ,@secondnibble int ,@tempint int ,@hexstring char(16) -- -- initialize and validate -- if (@pbinin IS NOT NULL) begin select @i = 0 ,@cbytesin = case when (@cbytesin > 0) then @cbytesin else DATALENGTH(@pbinin) end ,@pstrout = case when (@fsetprefix = 1) then N'0x' else N'' end ,@hexstring = '0123456789abcdef' if ( ((@cbytesin * 2) + 2 > 4000) or ((@cbytesin * 2) + 2 < 1) ) return NULL if ( ( @startoffset > @cbytesin ) or ( @startoffset < 1 ) ) return NULL -- -- do for each byte -- while (@i < @cbytesin) begin -- -- Each byte has two nibbles -- which we convert to character -- select @tempint = cast(substring(@pbinin, @i + @startoffset, 1) as int) select @firstnibble = @tempint / 16 select @secondnibble = @tempint % 16 -- -- we need to do an explicit cast with substring -- for proper string conversion. -- select @pstrout = @pstrout + cast(substring(@hexstring, (@firstnibble+1), 1) as nvarchar) + cast(substring(@hexstring, (@secondnibble+1), 1) as nvarchar) select @i = @i + 1 end end -- All done return @pstrout end go -- system function : returns string corresponding to version number part of setup path -- for the current instance raiserror(15339,-1,-1,'fn_MSsharedversion') GO CREATE FUNCTION dbo.fn_MSsharedversion ( @len_minorversion tinyint = 1 ) RETURNS NVARCHAR(10) AS BEGIN DECLARE @version VARCHAR(20), @bookmark_begin SMALLINT, @bookmark_end SMALLINT DECLARE @tools_ver VARCHAR(20) SELECT @version = CONVERT( VARCHAR(20), SERVERPROPERTY( N'PRODUCTVERSION') ) SELECT @bookmark_begin = CHARINDEX( '-', @version, 1) + 1 SELECT @bookmark_end = CHARINDEX( '.', @version, @bookmark_begin + 3 ) SELECT @version = SUBSTRING( @version, @bookmark_begin, @bookmark_end - @bookmark_begin ) SELECT @tools_ver = RTRIM(LTRIM(LEFT( @version, CHARINDEX('.', @version, 1) - 1 ) + LEFT(RIGHT( @version, CHARINDEX('.', @version, @len_minorversion ) ), @len_minorversion ))) RETURN @tools_ver END GO -- system procedure : Get install and data root paths (instance aware) raiserror(15339,-1,-1,'sp_MSget_setup_paths') GO CREATE PROCEDURE sp_MSget_setup_paths ( @sql_path NVARCHAR(260) = NULL OUTPUT, @data_path NVARCHAR(260) = NULL OUTPUT ) AS BEGIN DECLARE @retcode INTEGER DECLARE @regkey NVARCHAR(260) SET NOCOUNT ON declare @instance sysname select @instance = convert(sysname, SERVERPROPERTY('InstanceName')) select @regkey = 'SOFTWARE\Microsoft\' -- default installation if @instance is null SELECT @regkey = @regkey + 'MSSQLServer\Setup' else SELECT @regkey = @regkey + 'Microsoft SQL Server\' + @instance + '\Setup' EXECUTE @retcode = master.dbo.xp_regread 'HKEY_LOCAL_MACHINE', @regkey, 'SQLPath', @param = @sql_path OUTPUT IF ( @retcode <> 0 ) or ( @@ERROR <> 0 ) RETURN (1) EXECUTE @retcode = master.dbo.xp_regread 'HKEY_LOCAL_MACHINE', @regkey, 'SQLDataRoot', @param = @data_path OUTPUT IF ( @retcode <> 0 ) or ( @@ERROR <> 0 ) RETURN (1) RETURN (0) END GO -- No parameter checking is performed in sp_MSremoveoffloadparameter raiserror(15339,-1,-1,'sp_MSremoveoffloadparameter') GO CREATE PROCEDURE sp_MSremoveoffloadparameter ( @job_id VARBINARY(16), @agenttype NVARCHAR(20) ) AS SET NOCOUNT ON /* ** Declarations */ DECLARE @paramstart INT DECLARE @paramend INT DECLARE @paramlen INT DECLARE @paramend2 INT DECLARE @command NVARCHAR(3200) DECLARE @commandtail NVARCHAR(3200) DECLARE @pattern NVARCHAR(100) SELECT @pattern = N'%-[Oo][Ff][Ff][Ll][Oo][Aa][Dd]%' SELECT @paramlen = LEN(N'-offload') SELECT @command = NULL -- use the job_id and the agent type to retrieve the agent command -- line, only one agent command step is allowed in a job SELECT @command = command FROM msdb.dbo.sysjobsteps WHERE job_id = @job_id AND LOWER(subsystem collate SQL_Latin1_General_CP1_CS_AS) = LOWER(@agenttype collate SQL_Latin1_General_CP1_CS_AS) -- purge all instances of '-offload servername' from the agent command line SELECT @paramstart = PATINDEX(@pattern, @command) WHILE ((@command IS NOT NULL) AND (@paramstart <> 0)) BEGIN -- extract the part of the command line after the -Offload parameter SELECT @commandtail = SUBSTRING(@command, @paramstart + @paramlen, LEN(@command) - (@paramstart + @paramlen) + 1) -- search for the beginning of the server name that follows -offload -- in the command tail; note that the empty spaces in the square -- bracket of the pattern are actually a space and a tab SELECT @paramend = PATINDEX(N'%[^ ]%', @commandtail) -- search for the end of the server name that follows -offload IF (@paramend <> 0) BEGIN SELECT @commandtail = SUBSTRING(@commandtail, @paramend, LEN(@commandtail) - @paramend + 1) SELECT @paramend2 = PATINDEX(N'%[ ]%', @commandtail) IF (@paramend2 <> 0) BEGIN SELECT @paramend = @paramend + @paramend2 - 1 END ELSE BEGIN -- reaching the end of the command line SELECT @paramend = @paramend + LEN(@commandtail) - 1 IF @paramstart > 1 BEGIN SELECT @paramstart = @paramstart - 1 SELECT @paramend = @paramend + 1 END END END -- Remove the -Offload parameter from the command line SELECT @command = STUFF(@command, @paramstart, @paramlen + @paramend, N'') SELECT @paramstart = PATINDEX(@pattern, @command) END -- update the agent command line with all the -offload's removed UPDATE msdb.dbo.sysjobsteps SET command = @command WHERE job_id = @job_id AND LOWER(subsystem collate SQL_Latin1_General_CP1_CS_AS) = LOWER(@agenttype collate SQL_Latin1_General_CP1_CS_AS) RETURN 0 GO EXEC dbo.sp_MS_marksystemobject sp_MSremoveoffloadparameter GO -- No parameter checking is performed in sp_MSaddoffloadparameter raiserror(15339,-1,-1,'sp_MSaddoffloadparameter') GO CREATE PROCEDURE sp_MSaddoffloadparameter ( @offloadserver sysname, /* Name of the target server to offload the agent to */ @job_id VARBINARY(16), @agenttype NVARCHAR(20) /* Agent type can either be 'merge' or 'distribution' */ ) AS SET NOCOUNT ON /* ** Declarations */ DECLARE @command NVARCHAR(3200) -- initialize variables SELECT @command = NULL -- call sp_MSremoveoffloadparameter to remove all exisiting instances of the -- -offload parameters from the agent command line; the return status -- of sp_MSremoveoffloadparameter is ignored EXEC sp_MSremoveoffloadparameter @job_id=@job_id, @agenttype=@agenttype -- update the agent command line by appending '-Offload ' + -- @offloadserver UPDATE msdb.dbo.sysjobsteps SET command = command + N' -Offload ' + @offloadserver WHERE job_id = @job_id AND LOWER(subsystem collate SQL_Latin1_General_CP1_CS_AS) = LOWER(@agenttype collate SQL_Latin1_General_CP1_CS_AS) RETURN 0 GO EXEC dbo.sp_MS_marksystemobject sp_MSaddoffloadparameter GO -- -- System UDF fn_MSgensqescstr -- This function takes as input a varchar -- and stuffs an extra single quote for any single quotes in the string -- raiserror(15339,-1,-1,'fn_MSgensqescstr') go create function dbo.fn_MSgensqescstr ( @pstrin nvarchar(4000) ) returns nvarchar(4000) as begin declare @pstrout nvarchar(4000) select @pstrout = REPLACE(@pstrin, N'''', N'''''') return @pstrout end go raiserror(15339,-1,-1,'sp_MSUpgradeConflictTable') GO create proc sp_MSUpgradeConflictTable @skip_procgen bit = 0 AS declare @retcode int declare @conflict_table sysname declare @pubid uniqueidentifier declare @artid uniqueidentifier declare @ins_conflict_proc sysname declare @conflict_id int declare @objid int declare @qual_conflict nvarchar(132) if exists( select * from sysobjects where name = 'MSmerge_delete_conflicts' ) and not exists (select * from syscolumns where id = object_id('MSmerge_delete_conflicts') and name = 'create_time') begin alter table MSmerge_delete_conflicts add create_time datetime not null default getdate() end declare AC CURSOR LOCAL FAST_FORWARD for select conflict_table, objid, ins_conflict_proc, pubid, artid from sysmergearticles open AC fetch AC into @conflict_table, @objid, @ins_conflict_proc, @pubid, @artid while (@@fetch_status<>-1) begin if @conflict_table is NOT null begin select @conflict_id = object_id(@conflict_table) select @qual_conflict=QUOTENAME(@conflict_table) /* ** Upgrade conflict table so that it can get cleaned up later on */ if @conflict_id is not NULL and not exists (select name from syscolumns where name='MSrepl_create_time' and id=@conflict_id) begin exec ('alter table ' + @qual_conflict + ' add MSrepl_create_time datetime not null default getdate() ') if @@ERROR<>0 begin close AC deallocate AC return (1) end /* ** use create_time value for the new column before dropping create_time column, after making ** sure create_time is not from user table. */ if exists (select name from syscolumns where name='create_time' and id=@conflict_id) and not exists (select name from syscolumns where name='create_time' and id=@objid) begin exec ('update ' + @qual_conflict + ' set MSrepl_create_time=create_time') if @@ERROR<>0 begin close AC deallocate AC return (1) end declare @colid int declare @default_constraint sysname select @colid = colid from syscolumns where name='create_time' and id=@conflict_id select @default_constraint=object_name(constid) from sysconstraints where id=@conflict_id and colid=@colid /* ** drop default constrait on create_time column */ if @default_constraint is not NULL begin exec ('alter table ' + @qual_conflict + ' drop constraint ' + @default_constraint) if @@ERROR<>0 begin close AC deallocate AC return (1) end end exec ('alter table ' + @qual_conflict + ' drop column create_time') if @@ERROR<>0 begin close AC deallocate AC return (1) end end if @ins_conflict_proc is not NULL and object_id(@ins_conflict_proc) is not NULL begin exec ('drop procedure ' + @ins_conflict_proc) if @@ERROR<>0 begin close AC deallocate AC return (1) end --force to regenerate conflict insert proc to pick up the new column name update sysmergearticles set ins_conflict_proc=NULL where artid=@artid and pubid=@pubid if @@ERROR<>0 begin close AC deallocate AC return (1) end -- Do not upgrade conflict tables if this is called from sp_restoredbreplication, as -- the entire replication will be striped out. if @skip_procgen = 0 begin exec @retcode = sp_MSgetconflictinsertproc @artid, @pubid, 0 if @@ERROR<>0 or @retcode<>0 begin close AC deallocate AC return (1) end end end end if not exists (select * from sysindexes where id = @conflict_id and keys is not null) begin declare @rgcol sysname declare @indname sysname declare @quotedname sysname declare @owner sysname select @owner=user_name(uid) from sysobjects where id = @objid select @rgcol = QUOTENAME(name) from syscolumns where id = @objid and ColumnProperty(id, name, 'isrowguidcol') = 1 select @indname = 'uc_' + @conflict_table set @indname = QUOTENAME(@indname) set @quotedname = QUOTENAME(@owner) + '.' + QUOTENAME(@conflict_table) exec ('Create unique clustered index ' + @indname + ' on ' + @quotedname + ' (' + @rgcol + ', origin_datasource)' ) if @@ERROR <> 0 begin close AC deallocate AC return (1) end end end fetch next from AC into @conflict_table, @objid, @ins_conflict_proc, @pubid, @artid end close AC deallocate AC return (0) GO exec dbo.sp_MS_marksystemobject sp_MSUpgradeConflictTable Go -- -- This SP is used by the queued tran triggers to insert data into the SQL queue -- it enforces the security check and does the insert into the queue table -- Note this transaction is always called with a transaction (local or distributed) -- so do not add any save tran semantics -- raiserror(15339,-1,-1,'sp_MSsendtosqlqueue') GO go create proc sp_MSsendtosqlqueue ( @objid int ,@publisher sysname ,@publisher_db sysname ,@publication sysname ,@owner sysname ,@tranid sysname ,@data varbinary(8000) ,@datalen int ,@commandtype int = 1 ,@cmdstate bit = 0 ) as begin set nocount on -- -- Security check -- Make sure this proc is infact being called from the given object(trigger) -- if (trigger_nestlevel(@objid) = 0) begin raiserror(14126, 16, 2) return 1 end -- -- Security check: the caller of this SP has to be one of the -- predefined replication objects for this subscription -- if (@objid not in (select object_id(quotename(@owner) + N'.' + quotename(object_name)) from dbo.MSreplication_objects where publisher = @publisher and publisher_db = @publisher_db and publication = @publication and object_type = 'T')) begin raiserror(14126, 16, 3) return 1 end -- -- insert into the queue table -- insert into dbo.MSreplication_queue with (rowlock) (publisher,publisher_db,publication,tranid,data,datalen,commandtype,cmdstate) values(UPPER(@publisher),@publisher_db,@publication,@tranid,@data,@datalen,@commandtype,@cmdstate) if (@@error != 0) return 1 -- -- Update MSrepl_queuedtraninfo -- if exists (select * from dbo.MSrepl_queuedtraninfo with (nolock) where publisher = UPPER(@publisher) and publisher_db = @publisher_db and publication = @publication and tranid = @tranid) begin -- -- row for this transaction exists - update it -- update dbo.MSrepl_queuedtraninfo with (rowlock) set maxorderkey = @@identity ,commandcount = commandcount + 1 where publisher = UPPER(@publisher) and publisher_db = @publisher_db and publication = @publication and tranid = @tranid end else begin -- -- row for this transaction does not exist - insert it -- insert into dbo.MSrepl_queuedtraninfo with (rowlock) (publisher,publisher_db,publication,tranid,maxorderkey,commandcount) values (UPPER(@publisher),@publisher_db,@publication,@tranid,@@identity,1) end if (@@error != 0) return 1 -- -- all done -- return 0 end go exec dbo.sp_MS_marksystemobject sp_MSsendtosqlqueue go /* ** One and only one of these two parameters needs to be specified - meaning adjust publisher side ** identity range at publication level (all tables) or table level (whose name is given) */ raiserror(15339,-1,-1,'sp_adjustpublisheridentityrange') GO create procedure sp_adjustpublisheridentityrange ( @publication sysname = NULL, @table_name sysname = NULL, @table_owner sysname = NULL ) AS set nocount on declare @retcode int, @object_found bit declare @objid int declare @qualified_table_name nvarchar(260) declare @identity_support int declare @pubid uniqueidentifier select @object_found = 0 /* ** Security Check */ EXEC @retcode = dbo.sp_MSreplcheck_publish IF @@ERROR <> 0 or @retcode <> 0 return (1) if ((@publication is NULL and @table_name is NULL) or (@publication is NULL and @table_name is NULL) or (@publication is not NULL and @table_name is not NULL)) begin raiserror(21314, 16, -1, '@publication', '@table_name') return (1) end if @publication is NULL begin if @table_owner is NULL select @table_owner = user_name() select @qualified_table_name = QUOTENAME(@table_owner) + '.' + QUOTENAME(@table_name) select @objid = object_id(@qualified_table_name) if @objid is NULL begin RAISERROR (14027, 11, -1, @qualified_table_name) return (1) end end --Do this for merge? if exists (select * from sysobjects where name = 'sysmergepublications') begin if @publication is NULL begin select @identity_support = identity_support from sysmergearticles where objid=@objid if @identity_support is not null begin select @object_found = 1 if @identity_support = 0 return (0) exec @retcode = sp_MSadjustmergeidentity @tablename=@table_name if @retcode<>0 or @@ERROR<>0 begin raiserror(21315, 16, -1, @table_name) return (1) end end end if @table_name is NULL begin select @pubid=pubid FROM sysmergepublications WHERE name = @publication and UPPER(publisher)=UPPER(@@servername) and publisher_db=db_name() if @pubid is not null begin select @object_found = 1 if not exists (select * from sysmergearticles where pubid=@pubid and identity_support=1) return (0) exec @retcode = sp_MSadjustmergeidentity @publication=@publication if @retcode<>0 or @@ERROR<>0 begin raiserror(21316, 16, -1, @publication) return (1) end end end end if exists (select * from sysobjects where name = 'syspublications') begin if @publication is NULL begin declare @artid int select top 1 @artid = artid from sysarticles where objid = @objid if @artid is not null begin select @object_found = 1 exec @retcode = sp_MSpub_adjust_identity @artid if @retcode<>0 or @@ERROR<>0 return (1) end end else begin declare @publication_id int select @publication_id = pubid from syspublications where name = @publication if @publication_id is not null begin select @object_found = 1 DECLARE adjust_identity CURSOR LOCAL FAST_FORWARD FOR SELECT art1.objid FROM sysarticles art1, sysarticleupdates art2 where art1.pubid = @publication_id and art1.artid = art2.artid and art2.identity_support = 1 and (art1.artid = @artid or @artid is null) FOR READ ONLY OPEN adjust_identity FETCH adjust_identity INTO @objid WHILE (@@fetch_status <> -1) begin exec @retcode = sp_MSpub_adjust_identity @artid if @retcode<>0 or @@ERROR<>0 return (1) FETCH adjust_identity INTO @objid end end end end if @object_found = 0 begin if @publication is null raiserror(21246, 16, -1, @qualified_table_name) else RAISERROR (20026, 11, -1, @publication) end RETURN (0) GO exec dbo.sp_MS_marksystemobject sp_adjustpublisheridentityrange GO grant execute on dbo.sp_adjustpublisheridentityrange to public GO -- sp_MSestimate(merge)snapshotworkload is called exclusively by the -- snapshot agent to estimate the amount of work that has to be done for -- a snapshot session and a breakdown of the work load into subtasks raiserror(15339,-1,-1,'sp_MSestimatemergesnapshotworkload') GO create proc sp_MSestimatemergesnapshotworkload ( @publication sysname ) as begin set nocount on declare @taskload int declare @bigtaskload bigint declare @table_created bit declare @retcode int -- constant declare @zerouuid uniqueidentifier select @zerouuid = convert(uniqueidentifier, N'{00000000-0000-0000-0000-000000000000}') -- Publication info declare @pubid uniqueidentifier declare @compress_snapshot bit declare @snapshot_in_defaultfolder bit declare @alt_snapshot_folder nvarchar(255) declare @enabled_for_internet bit declare @ftp_password nvarchar(524) declare @ftp_subdirectory nvarchar(255) declare @pre_snapshot_script nvarchar(255) declare @post_snapshot_script nvarchar(255) declare @dynamic_filters bit -- Per publication summary stats declare @numarticles int declare @totalrowcount int declare @needsysprescript bit declare @copysnapshot bit declare @deletefiles bit declare @scriptproccost int declare @addcommandstotal int declare @numscripts int declare @totalbcpcostper100 int declare @numprescriptcommands int declare @numunsyncedarticles int declare @numtablearticles int declare @systablesrowcount int declare @maxint int select @numarticles = 0 select @totalrowcount = 0 select @needsysprescript = 0 select @copysnapshot = 0 select @deletefiles = 0 select @scriptproccost = 0 select @deletefiles = 0 select @addcommandstotal = 0 select @numscripts = 0 select @totalbcpcostper100 = 0 select @numprescriptcommands = 0 select @numunsyncedarticles = 0 select @numtablearticles = 0 select @systablesrowcount = 0 select @maxint = 2147483647 -- Per article variables declare @artid uniqueidentifier declare @schema_option int declare @creation_script nvarchar(255) declare @type tinyint declare @objid int declare @rowcount int declare @name sysname declare @status int -- Security check select @retcode = 0 EXEC @retcode = dbo.sp_MSreplcheck_publish IF @@ERROR <> 0 or @retcode <> 0 return (1) select @table_created = 0 select @pubid = null select @compress_snapshot = 0 select @snapshot_in_defaultfolder = 0 select @alt_snapshot_folder = null select @enabled_for_internet = 0 select @ftp_password = null select @ftp_subdirectory = null select @pre_snapshot_script = null select @post_snapshot_script = null -- Validate publication and retrieve publication information select @pubid = pubid, @compress_snapshot = compress_snapshot, @snapshot_in_defaultfolder = snapshot_in_defaultfolder, @alt_snapshot_folder = alt_snapshot_folder, @enabled_for_internet = enabled_for_internet, @ftp_password = ftp_password, @ftp_subdirectory = ftp_subdirectory, @pre_snapshot_script = pre_snapshot_script, @post_snapshot_script = post_snapshot_script, @dynamic_filters = dynamic_filters from sysmergepublications where name = @publication and upper(@@servername) = publisher and publisher_db = db_name() if @pubid = null begin raiserror(20026, 11, -1, @publication) return (1) end -- An artid of -1 means the task is a per publication -- task -- Task id mapping - This is the list of task whose completion can be -- reported by the snapshot agent -- 0 - Total workload (not really a task) -- 1 - Schema script generation -- 2 - Trigger script generation -- 3 - XProp script generation -- 4 - Bcp file generation -- 5 - Activating subscription (estimate number of subscriptions?) -- 6 - Adding snapshot commands -- 7 - System pre-script generation -- 8 - Flushing folder for scripts -- 9 - Constraint script generation -- 10 - Copying pre-script -- 11 - Copying post-script -- 12 - Copying custom schema creation script -- 13 - Index script generation -- 14 - Flushing the cabinet -- 15 - Adding rowguid column -- 16 - Setting article procs -- 17 - Adding merge triggers -- 18 - Generating system table scripts -- 19 - Generating system table bcp files -- 20 - Making publication generation -- 21 - Generating and setting conflict script -- 22 - Generating publication views -- Weights and overheads -- DMO Script generation - 7/script -- BCP 5 overhead + 5/100 rows -- Flush folder for bcp 2/100 rows -- Delete file 2 -- System pre-snapshot script 1 overhead + 0.5/pre-creation command -- Copying user file 2 -- Adding file to cabinet 1 for scripts and 1/100 rows in bcp file -- Loading article info 3 -- Delete bcp file 2/100rows -- Copy bcp file 2/100rows -- Flush scripts folder 1/2 scripts -- Flushing cabinet per 5 scripts 1 -- Flushing cabinet per 500 rows 1 -- Script execution 3 -- Adding rowguid columns 20/100 rows -- Adding merge triggers 7 -- Setting article procs 5 -- Here is the list of cost factors declare @addcommandcost int declare @dmoscriptcost int declare @bcpoverhead int declare @bcpcostper100 int declare @flushper100 int declare @flushperscript int declare @delfilecost int declare @syspreoverhead int declare @syspreper2commands int declare @addbcptocabper100 int declare @addscripttocab int declare @copyfilecost int declare @loadartinfo int declare @deletebcpper100 int declare @copybcpper100 int declare @flushper2scripts int declare @flushcabper5scripts int declare @flushcabper500bcprows int declare @scriptexeccost int declare @rowguidper100 int declare @addmergetriggers int declare @setartprocs int declare @pubviewperarticle int declare @genperarticle int select @addcommandcost = 2 select @dmoscriptcost = 7 select @bcpcostper100 = 20 select @bcpoverhead = 2 select @flushper100 = 2 select @flushperscript = 3 select @delfilecost = 2 select @syspreoverhead = 1 select @syspreper2commands = 1 select @addbcptocabper100 = 1 select @addscripttocab = 1 select @copyfilecost = 2 select @loadartinfo = 3 select @deletebcpper100 = 1 select @copybcpper100 = 2 select @flushper2scripts = 1 select @flushcabper5scripts = 1 select @flushcabper500bcprows = 1 select @scriptexeccost = 3 select @rowguidper100 = 20 select @addmergetriggers = 3 select @pubviewperarticle = 2 select @genperarticle = 2 select @setartprocs = 5 create table #workload_breakdown ( name sysname collate database_default, artid uniqueidentifier, taskid int, taskload int ) if @@error <> 0 goto Failure select @table_created = 1 -- Per publication work load estimate that can be done using publication -- properties alone -- Adding snapshot header commands -- Snapshot header begins + Snapshot header ends + -- directory command + Snapshot trailer command = 3 * @addcommandcost select @addcommandstotal = 4 -- Alternate snapshot folder = 1 * @addcommandcost if @alt_snapshot_folder is not null and @alt_snapshot_folder <> N'' and @snapshot_in_defaultfolder = 1 begin select @addcommandstotal = @addcommandstotal + @addcommandcost end -- Ftp commands if @enabled_for_internet = 1 begin -- ftp_address and ftp_port must be there +=2 * @addcommandcost select @addcommandstotal = @addcommandstotal + 2 * @addcommandcost -- ftp_password += 1 * @addcommandcost if @ftp_password is not null and @ftp_password <> N'' begin select @addcommandstotal = @addcommandstotal + @addcommandcost end -- ftp_subdirectory += 1 * @addcommandcost if @ftp_subdirectory is not null and @ftp_subdirectory <> N'' begin select @addcommandstotal = @addcommandstotal + 1 * @addcommandcost end end -- Compressed archive path if @compress_snapshot = 1 begin select @addcommandstotal = @addcommandstotal + 1 * @addcommandcost end -- Snapshot trailer command select @addcommandstotal = @addcommandstotal + @addcommandcost -- Need to copy files? if @alt_snapshot_folder is not null and @alt_snapshot_folder <> N'' and @snapshot_in_defaultfolder = 1 and @compress_snapshot = 0 begin select @copysnapshot = 1 end -- Compute per-script file post processing cost and bcp cost per 100 rows -- Need to delete files? if (@alt_snapshot_folder is null or @alt_snapshot_folder <> N'' or @snapshot_in_defaultfolder = 0) and @compress_snapshot = 1 begin select @deletefiles = 1 end select @totalbcpcostper100 = @bcpcostper100 -- Copy file? if @copysnapshot = 1 begin select @scriptproccost = @scriptproccost + @copyfilecost select @totalbcpcostper100 = @totalbcpcostper100 + @copybcpper100 end -- Add file to cabinet? if @compress_snapshot = 1 begin select @scriptproccost = @scriptproccost + @addscripttocab select @totalbcpcostper100 = @totalbcpcostper100 + @addbcptocabper100 end -- Delete file? if @deletefiles = 1 begin select @scriptproccost = @scriptproccost + @delfilecost select @totalbcpcostper100 = @totalbcpcostper100 + @deletebcpper100 end -- Pre/Post-snapshot scripts, has to be computed after the -- the per-script post-processing cost is calculated if @pre_snapshot_script is not null and @pre_snapshot_script <> N'' begin -- Cost of copying the script file select @taskload = @copyfilecost + @scriptproccost insert #workload_breakdown values (N'', @zerouuid, 10, @taskload) -- Cost of adding the pre-snapshot command select @addcommandstotal = @addcommandstotal + @addcommandcost -- Increment scripts counter select @numscripts = @numscripts + 1 end if @post_snapshot_script is not null and @post_snapshot_script <> N'' begin -- Cost of copying the script file select @taskload = @copyfilecost + @scriptproccost insert #workload_breakdown values (N'', @zerouuid, 11, @taskload) -- Cost of adding the post-snapshot command select @addcommandstotal = @addcommandstotal + @addcommandcost -- Increment scripts counter select @numscripts = @numscripts + 1 end -- Estimate the break down of per article tasks declare hCarticles cursor local fast_forward for select artid, creation_script, objid, convert(int, schema_option), type, name, status from sysmergeextendedarticlesview where pubid = @pubid open hCarticles fetch hCarticles into @artid, @creation_script, @objid, @schema_option, @type, @name, @status while (@@fetch_status <> -1) begin if @type = 0x40 -- Schema view articles, may require index scripting begin select @taskload = 0 -- See if a custom creation script will be used if @schema_option = 0 and @creation_script is not null and @creation_script <> N'' begin -- Script generation select @taskload = @copyfilecost + @scriptproccost insert #workload_breakdown values (@name, @artid, 12, @taskload) -- Cost of adding commands for the custom script select @addcommandstotal = @addcommandstotal + @addcommandcost -- Increment scripts counter select @numscripts = @numscripts + 1 -- No need to worry about index script end else begin -- Script generation select @taskload = @dmoscriptcost + @scriptproccost -- Must script out schema script insert #workload_breakdown values (@name, @artid, 1, @taskload) -- Cost of adding the command select @addcommandstotal = @addcommandstotal + @addcommandcost -- Increment scripts counter select @numscripts = @numscripts + 1 -- DRI script containing the view's indexes? if (@schema_option & 0x50) <> 0x0 begin -- Cost of script generation select @taskload = @dmoscriptcost + @scriptproccost insert #workload_breakdown values (@name, @artid, 9, @taskload) -- Cost of adding command for the script select @addcommandstotal = @addcommandstotal + @addcommandcost -- Increment scripts counter select @numscripts = @numscripts + 1 end -- Trigger script? if (@schema_option & 0x100) <> 0x0 begin -- Cost of script generation select @taskload = @dmoscriptcost + @scriptproccost insert #workload_breakdown values (@name, @artid, 2, @taskload) -- Cost of adding command for the script select @addcommandstotal = @addcommandstotal + @addcommandcost -- Increment scripts counter select @numscripts = @numscripts + 1 end -- XProp script? if (@schema_option & 0x2000) <> 0x0 begin -- Cost of script generation select @taskload = @dmoscriptcost + @scriptproccost insert #workload_breakdown values (@name, @artid, 3, @taskload) -- Cost of adding command select @addcommandstotal = @addcommandstotal + @addcommandcost -- Increment scripts counter select @numscripts = @numscripts + 1 end end end else if @type in (0x08, 0x18, 0x20, 0x80) -- Regular schema articles begin select @taskload = 0 -- See if a custom creation script will be used if @schema_option = 0 and @creation_script is not null and @creation_script <> N'' begin -- Script generation select @taskload = @copyfilecost + @scriptproccost insert #workload_breakdown values (@name, @artid, 12, @taskload) -- Cost of adding commands for the custom script select @addcommandstotal = @addcommandstotal + @addcommandcost -- Increment scripts counter select @numscripts = @numscripts + 1 end else begin -- Script generation select @taskload = @dmoscriptcost + @scriptproccost -- Must script out schema script insert #workload_breakdown values (@name, @artid, 1, @taskload) -- Cost of adding the command select @addcommandstotal = @addcommandstotal + @addcommandcost -- Increment scripts counter select @numscripts = @numscripts + 1 -- XProp script? if (@schema_option & 0x2000) <> 0x0 begin -- Cost of script generation select @taskload = @dmoscriptcost + @scriptproccost insert #workload_breakdown values (@name, @artid, 3, @taskload) -- Cost of adding command select @addcommandstotal = @addcommandstotal + @addcommandcost -- Increment scripts counter select @numscripts = @numscripts + 1 end end end else -- Merge table articles, requires bcp begin select @taskload = 0 -- See if a custom creation script will be used if @schema_option = 0 and @creation_script is not null and @creation_script <> N'' begin -- Script generation select @taskload = @copyfilecost + @scriptproccost insert #workload_breakdown values (@name, @artid, 12, @taskload) -- Cost of adding commands for the custom script select @addcommandstotal = @addcommandstotal + @addcommandcost -- Increment scripts counter select @numscripts = @numscripts + 1 -- No need to worry about index script end else begin -- Script generation select @taskload = @dmoscriptcost + @scriptproccost -- Must script out schema script insert #workload_breakdown values (@name, @artid, 1, @taskload) -- Cost of adding the command select @addcommandstotal = @addcommandstotal + @addcommandcost -- Increment scripts counter select @numscripts = @numscripts + 1 -- Constraint script is not optional for merge table article -- Cost of script generation select @taskload = @dmoscriptcost + @scriptproccost insert #workload_breakdown values (@name, @artid, 9, @taskload) -- Cost of adding command for the script select @addcommandstotal = @addcommandstotal + @addcommandcost -- Increment scripts counter select @numscripts = @numscripts + 1 -- Trigger script? if (@schema_option & 0x100) <> 0x0 begin -- Cost of script generation select @taskload = @dmoscriptcost + @scriptproccost insert #workload_breakdown values (@name, @artid, 2, @taskload) -- Cost of adding command for the script select @addcommandstotal = @addcommandstotal + @addcommandcost -- Increment scripts counter select @numscripts = @numscripts + 1 end -- XProp script? if (@schema_option & 0x2000) <> 0x0 begin -- Cost of script generation select @taskload = @dmoscriptcost + @scriptproccost insert #workload_breakdown values (@name, @artid, 3, @taskload) -- Cost of adding command select @addcommandstotal = @addcommandstotal + @addcommandcost -- Increment scripts counter select @numscripts = @numscripts + 1 end end -- Conflict script generation and setting -- Cost of script generation and execution select @taskload = @dmoscriptcost + @scriptexeccost + @scriptproccost insert #workload_breakdown values (@name, @artid, 21, @taskload) -- Get fast row count from sysindexes for bcp op estimation select @rowcount = case when isnull(rowcnt,0) > @maxint then @maxint / 10000 when isnull(rowcnt,0) > @maxint / 10000 then rowcnt / 10000 else isnull(rowcnt,0) end from sysindexes where id = @objid and indid in (0,1) -- For unsynced articles, we need to -- 1) Add rowguid column -- 2) Set article procs -- 3) Add merge triggers if @status = 1 begin -- Add rowguid column - use article row count to estimate the cost select @taskload = (@rowcount * @rowguidper100) / 100 insert #workload_breakdown values (@name, @artid, 15, @taskload) -- Set article procs select @taskload = @setartprocs insert #workload_breakdown values (@name, @artid, 16, @taskload) -- Add merge triggers select @taskload = @addmergetriggers insert #workload_breakdown values (@name, @artid, 17, @taskload) -- Increment the number of unsynced articles select @numunsyncedarticles = @numunsyncedarticles + 1 end -- Increment the total row count select @totalrowcount = @totalrowcount + @rowcount -- BCP computation -- Bcp file generation select @taskload = @bcpoverhead + (@rowcount * @totalbcpcostper100) / 100 insert #workload_breakdown values (@name, @artid, 4, @taskload) -- Increment the table articles counter select @numtablearticles = @numtablearticles + 1 end -- System pre-snapshot script required? if @type in (0x40, 0x80) begin select @needsysprescript = 1 -- Incrememt the number of pre-script command counter select @numprescriptcommands = @numprescriptcommands + 1 end -- Increment the article count select @numarticles = @numarticles + 1 fetch hCarticles into @artid, @creation_script, @objid, @schema_option, @type, @name, @status end -- The cost of making publication views depends upon the -- number of unsynced articles if @numunsyncedarticles <> 0 begin select @taskload = @numunsyncedarticles * @pubviewperarticle insert #workload_breakdown values (N'', @zerouuid, 22, @taskload) end -- Make publication generation - roughly proportional to the number of table -- articles we have select @taskload = @numtablearticles * @genperarticle insert #workload_breakdown values (N'', @zerouuid, 20, @taskload) -- Merge system tables processing -- Script files select @taskload = 4 * (@dmoscriptcost + @scriptproccost) insert #workload_breakdown values (N'', @zerouuid, 18, @taskload) -- Cost of adding the commands select @addcommandcost = @addcommandcost + 4 -- Bcp files - Generated only when the publication is not enabled for -- dynamic filters if @dynamic_filters = 0 begin if exists (select * from sysobjects where name = N'MSmerge_contents') begin select @rowcount = case when isnull(rowcnt,0) > @maxint then @maxint / 10000 when isnull(rowcnt,0) > @maxint / 10000 then rowcnt / 10000 else isnull(rowcnt,0) end from sysindexes where id = object_id('dbo.MSmerge_contents') and indid in (0,1) select @systablesrowcount = @systablesrowcount + @rowcount end if exists (select * from sysobjects where name = N'MSmerge_tombstones') begin select @rowcount = case when isnull(rowcnt,0) > @maxint then @maxint / 10000 when isnull(rowcnt,0) > @maxint / 10000 then rowcnt / 10000 else isnull(rowcnt,0) end from sysindexes where id = object_id('dbo.MSmerge_tombstoness') and indid in (0,1) select @systablesrowcount = @systablesrowcount + @rowcount end if exists (select * from sysobjects where name = N'MSmerge_genhistory') begin select @rowcount = case when isnull(rowcnt,0) > @maxint then @maxint / 10000 when isnull(rowcnt,0) > @maxint / 10000 then rowcnt / 10000 else isnull(rowcnt,0) end from sysindexes where id = object_id('dbo.MSmerge_genhistory') and indid in (0,1) select @systablesrowcount = @systablesrowcount + @rowcount end end if exists (select * from sysobjects where name = N'sysmergesubsetfilters') begin select @rowcount = count(*) from sysmergesubsetfilters select @systablesrowcount = @systablesrowcount + @rowcount end select @taskload = (4 * @bcpoverhead) + (@systablesrowcount * @totalbcpcostper100) / 100 insert #workload_breakdown values (N'', @zerouuid, 19, @taskload) select @totalrowcount = @totalrowcount + @systablesrowcount -- System pre-snapshot script processing cost if @needsysprescript = 1 begin select @taskload = @syspreoverhead + (@numprescriptcommands * @syspreper2commands) / 2 + @scriptproccost insert #workload_breakdown values (N'', @zerouuid, 7, @taskload) select @numscripts = @numscripts + 1 end -- Cost of flushing folder for the scripts if @compress_snapshot = 1 begin select @taskload = (@numscripts * @flushper2scripts) / 2 insert #workload_breakdown values (N'', @zerouuid, 8, @taskload) end -- Cost for flushing the cabinet if @compress_snapshot = 1 begin select @taskload = (@numscripts * @flushcabper5scripts / 5) + (@totalrowcount * @flushcabper500bcprows / 500) insert #workload_breakdown values (N'', @zerouuid, 14, @taskload) end -- Add the total add commands cost insert #workload_breakdown values (N'', @zerouuid, 6, @addcommandstotal) -- Compute the total workload and put that in the -- workload break down select @bigtaskload = sum(convert(bigint,taskload)) from #workload_breakdown select @taskload = case when @bigtaskload > @maxint then @maxint else @bigtaskload end insert #workload_breakdown values (N'', @zerouuid, 0, @taskload) select name, taskid, taskload from #workload_breakdown order by artid, taskid asc drop table #workload_breakdown return 0 Failure: if @table_created = 1 drop table #workload_breakdown return 1 end go exec dbo.sp_MS_marksystemobject sp_MSestimatemergesnapshotworkload go grant execute on dbo.sp_MSestimatemergesnapshotworkload to public go raiserror(15339,-1,-1,'sp_MSestimatesnapshotworkload') go create proc sp_MSestimatesnapshotworkload ( @publication sysname ) as begin set nocount on declare @taskload int declare @bigtaskload bigint declare @table_created bit declare @retcode int -- Publication info declare @pubid int declare @compress_snapshot bit declare @snapshot_in_defaultfolder bit declare @alt_snapshot_folder nvarchar(255) declare @enabled_for_internet bit declare @ftp_password nvarchar(524) declare @ftp_subdirectory nvarchar(255) declare @pre_snapshot_script nvarchar(255) declare @post_snapshot_script nvarchar(255) -- Per publication summary stats declare @numarticles int declare @totalrowcount int declare @needsysprescript bit declare @copysnapshot bit declare @deletefiles bit declare @scriptproccost int declare @addcommandstotal int declare @numscripts int declare @totalbcpcostper100 int declare @numprescriptcommands int select @numarticles = 0 select @totalrowcount = 0 select @needsysprescript = 0 select @copysnapshot = 0 select @deletefiles = 0 select @scriptproccost = 0 select @deletefiles = 0 select @addcommandstotal = 0 select @numscripts = 0 select @totalbcpcostper100 = 0 select @numprescriptcommands = 0 -- Per article variables declare @artid int declare @schema_option int declare @creation_script nvarchar(255) declare @type tinyint declare @objid int declare @rowcount int declare @name sysname declare @pre_creation_command int select @table_created = 0 -- Security check select @retcode = 0 EXEC @retcode = dbo.sp_MSreplcheck_publish IF @@ERROR <> 0 or @retcode <> 0 return (1) select @pubid = null select @compress_snapshot = 0 select @snapshot_in_defaultfolder = 0 select @alt_snapshot_folder = null select @enabled_for_internet = 0 select @ftp_password = null select @ftp_subdirectory = null select @pre_snapshot_script = null select @post_snapshot_script = null -- Validate publication and retrieve publication information select @pubid = pubid, @compress_snapshot = compress_snapshot, @snapshot_in_defaultfolder = snapshot_in_defaultfolder, @alt_snapshot_folder = alt_snapshot_folder, @enabled_for_internet = enabled_for_internet, @ftp_password = ftp_password, @ftp_subdirectory = ftp_subdirectory, @pre_snapshot_script = pre_snapshot_script, @post_snapshot_script = post_snapshot_script from syspublications where name = @publication if @pubid = null begin raiserror(20026, 11, -1, @publication) return (1) end -- An artid of -1 means the task is a per publication -- task -- Task id mapping - This is the list of task whose completion can be -- reported by the snapshot agent -- 0 - Total workload (not really a task) -- 1 - Schema script generation -- 2 - Trigger script generation -- 3 - XProp script generation -- 4 - Bcp file generation -- 5 - Activating subscription (estimate number of subscriptions?) -- 6 - Adding snapshot commands -- 7 - System pre-script generation -- 8 - Flushing folder for scripts -- 9 - Constraint script generation -- 10 - Copying pre-script -- 11 - Copying post-script -- 12 - Copying custom schema creation script -- 13 - Index script generation -- 14 - Flushing the cabinet -- 15 - Adding rowguid column -- 16 - Setting article procs -- 17 - Adding merge triggers -- 18 - Generating system table scripts -- 19 - Generating system table bcp files -- 20 - Making publication generation -- 21 - Generating and setting conflict script -- 22 - Generating publication views -- Weights and overheads -- DMO Script generation - 7/script -- BCP 5 overhead + 5/100 rows -- Flush folder for bcp 2/100 rows -- Delete file 2 -- System pre-snapshot script 1 overhead + 0.5/pre-creation command -- Copying user file 2 -- Adding file to cabinet 1 for scripts and 1/100 rows in bcp file -- Loading article info 3 -- Delete bcp file 2/100rows -- Copy bcp file 2/100rows -- Flush scripts folder 1/2 scripts -- Flushing cabinet per 5 scripts 1 -- Flushing cabinet per 500 rows 1 -- Here is the list of cost factors declare @addcommandcost int declare @dmoscriptcost int declare @bcpoverhead int declare @bcpcostper100 int declare @flushper100 int declare @flushperscript int declare @delfilecost int declare @syspreoverhead int declare @syspreper2commands int declare @addbcptocabper100 int declare @addscripttocab int declare @copyfilecost int declare @loadartinfo int declare @deletebcpper100 int declare @copybcpper100 int declare @flushper2scripts int declare @flushcabper5scripts int declare @flushcabper500bcprows int declare @maxint int select @addcommandcost = 2 select @dmoscriptcost = 7 select @bcpcostper100 = 20 select @bcpoverhead = 2 select @flushper100 = 2 select @flushperscript = 3 select @delfilecost = 2 select @syspreoverhead = 1 select @syspreper2commands = 1 select @addbcptocabper100 = 1 select @addscripttocab = 1 select @copyfilecost = 2 select @loadartinfo = 3 select @deletebcpper100 = 1 select @copybcpper100 = 2 select @flushper2scripts = 1 select @flushcabper5scripts = 1 select @flushcabper500bcprows = 1 select @maxint = 2147483647 create table #workload_breakdown ( name sysname collate database_default, artid int, taskid int, taskload int ) if @@error <> 0 goto Failure select @table_created = 1 -- Per publication work load estimate that can be done using publication -- properties alone -- Adding snapshot header commands -- Snapshot header begins + Snapshot header ends + -- directory command + Snapshot trailer command = 3 * @addcommandcost select @addcommandstotal = 4 -- Alternate snapshot folder = 1 * @addcommandcost if @alt_snapshot_folder is not null and @alt_snapshot_folder <> N'' and @snapshot_in_defaultfolder = 1 begin select @addcommandstotal = @addcommandstotal + @addcommandcost end -- Ftp commands if @enabled_for_internet = 1 begin -- ftp_address and ftp_port must be there +=2 * @addcommandcost select @addcommandstotal = @addcommandstotal + 2 * @addcommandcost -- ftp_password += 1 * @addcommandcost if @ftp_password is not null and @ftp_password <> N'' begin select @addcommandstotal = @addcommandstotal + @addcommandcost end -- ftp_subdirectory += 1 * @addcommandcost if @ftp_subdirectory is not null and @ftp_subdirectory <> N'' begin select @addcommandstotal = @addcommandstotal + 1 * @addcommandcost end end -- Compressed archive path if @compress_snapshot = 1 begin select @addcommandstotal = @addcommandstotal + 1 * @addcommandcost end -- Snapshot trailer command select @addcommandstotal = @addcommandstotal + @addcommandcost -- Need to copy files? if @alt_snapshot_folder is not null and @alt_snapshot_folder <> N'' and @snapshot_in_defaultfolder = 1 and @compress_snapshot = 0 begin select @copysnapshot = 1 end -- Compute per-script file post processing cost and bcp cost per 100 rows -- Need to delete files? if (@alt_snapshot_folder is null or @alt_snapshot_folder <> N'' or @snapshot_in_defaultfolder = 0) and @compress_snapshot = 1 begin select @deletefiles = 1 end select @totalbcpcostper100 = @bcpcostper100 -- Copy file? if @copysnapshot = 1 begin select @scriptproccost = @scriptproccost + @copyfilecost select @to